Short answer
- Yes, for a Cloud Run “push” work pool it’s normal to have zero workers. No worker should be attached.
- “Late” means your server didn’t start the run on time. In self‑hosted setups this is usually one of:
- Your CLI created the pool/deployment in the wrong API (e.g., Prefect Cloud instead of your self‑hosted server)
- The work pool is paused or misconfigured (missing region/image/service_account_name/credentials)
- The scheduler service isn’t running on your server
- The server lacks GCP permissions to create Cloud Run Jobs
Do this, step by step
1) Make sure your CLI is pointed at your self‑hosted server
- Check:
- prefect config view
- Ensure PREFECT_API_URL is your self‑hosted DNS, e.g.
https://your-prefect.example.com/api
- If not, set it (and basic auth for the CLI):
- export PREFECT_API_URL="
https://your-prefect.example.com/api"
- export PREFECT_API_AUTH_STRING="my-user:my-pass"
- Verify you see your pool on your server, not in Cloud:
- prefect work-pool ls
- prefect work-pool inspect gcr-pool
If you don’t see it, you created it against the wrong API. Recreate it now that your CLI points to your server.
Docs:
- Self-hosted server CLI config:
https://docs.prefect.io/v3/how-to-guides/self-hosted/server-cli
2) Confirm the scheduler is actually running on your self‑hosted server
- If the scheduler isn’t running, runs will go Late forever.
- In Kubernetes:
- kubectl get pods -n <namespace> and identify the server pod
- kubectl logs <server-pod> and look for “Scheduler” logs and periodic scheduling messages
- You can also exec into the server pod and run:
- prefect server services list-services
It should list “Scheduler” running. If it’s not, ensure your Helm values haven’t disabled services and redeploy.
Docs:
- Server Helm overview:
https://docs.prefect.io/v3/advanced/server-helm
3) Ensure the Cloud Run work pool is Active and complete
- Status:
- prefect work-pool inspect gcr-pool
- If paused: prefect work-pool resume gcr-pool
- Verify the base job template has the required fields:
- prefect work-pool get-default-base-job-template --type cloud-run --file cloud-run-default.json
Compare with your pool’s template. You must set at least:
- region
- image
- service_account_name
- credentials (optional if you use Workload Identity on the server)
- env should include:
- PREFECT_API_URL=
https://your-prefect.example.com/api
- PREFECT_API_AUTH_STRING=my-user:my-pass
Update if needed:
- prefect work-pool update gcr-pool --base-job-template cloud-run-template.json
Docs:
- Cloud Run guide and variables:
https://docs.prefect.io/v3/how-to-guides/deployment_infra/serverless#google-cloud-run-4
- GCP worker guide (roles, template fields):
https://docs.prefect.io/v3/integrations/prefect-gcp/gcp-worker-guide
4) Confirm your deployment actually targets that pool
- List and inspect:
- prefect deployment ls
- prefect deployment inspect <deployment-name>
Ensure work_pool_name = gcr-pool.
5) Test a run now and watch server logs
- Start a run immediately:
- prefect deployment run <deployment-name>
- Tail the server logs:
- kubectl logs -f <server-pod>
If the server cannot create the Cloud Run Job, you’ll see a clear error (permissions, bad region/SA, invalid template, etc.).
6) Sanity‑check GCP permissions from the server
- If you used GKE Workload Identity:
- The server pod’s KSA should be annotated with
iam.gke.io/gcp-service-account: <gsa>@<project>.
iam.gserviceaccount.com
- That GSA needs roles:
- roles/run.developer (or run.admin)
- roles/iam.serviceAccountUser on the runtime SA specified in service_account_name
- Artifact Registry read if your image is private
- If you did not use Workload Identity:
- Either mount a JSON key and set GOOGLE_APPLICATION_CREDENTIALS in the server pod, or put the JSON in the pool template’s credentials field.
7) Optional: provision infra to surface errors early