GoogleContainerTools/skaffold · error
DEPLOY_CLOUD_RUN_UPDATE_SERVICE_ERR
DEPLOY_CLOUD_RUN_UPDATE_SERVICE_ERR
Error message
error deploying Cloud Run Service: %s
What it means
After determining the service exists or not, `deployService` performs the actual write: `Services.Create` for a new service or `Services.ReplaceService` for an existing one. Any error from either call's `.Do()` is wrapped as 'error deploying Cloud Run Service: %s' with code DEPLOY_CLOUD_RUN_UPDATE_SERVICE_ERR.
Source
Thrown at pkg/skaffold/deploy/cloudrun/deploy.go:307
_, err := getCall.Do()
if err != nil {
gErr, ok := err.(*googleapi.Error)
if !ok || gErr.Code != http.StatusNotFound {
return nil, sErrors.NewError(fmt.Errorf("error checking Cloud Run State: %w", err), &proto.ActionableErr{
Message: err.Error(),
ErrCode: proto.StatusCode_DEPLOY_CLOUD_RUN_GET_SERVICE_ERR,
})
}
// This is a new service, we need to create it
createCall := crclient.Projects.Locations.Services.Create(parent, service)
_, err = createCall.Do()
} else {
replaceCall := crclient.Projects.Locations.Services.ReplaceService(sName, service)
_, err = replaceCall.Do()
}
if err != nil {
return nil, sErrors.NewError(fmt.Errorf("error deploying Cloud Run Service: %s", err), &proto.ActionableErr{
Message: err.Error(),
ErrCode: proto.StatusCode_DEPLOY_CLOUD_RUN_UPDATE_SERVICE_ERR,
})
}
return &resName, nil
}
func (d *Deployer) forceSendValueOfMaxRetries(job *run.Job, manifest []byte) {
maxRetriesPath := []string{"spec", "template", "spec", "template", "spec"}
node := make(map[string]interface{})
if err := k8syaml.Unmarshal(manifest, &node); err != nil {
logger.Entry(context.TODO()).Debugf("Error unmarshaling job into map, skipping maxRetries ForceSendFields logic: %v", err)
return
}
for _, field := range maxRetriesPath {
value := node[field]View on GitHub (pinned to a1189de023)
Solutions
- Read the API message in the error (it's surfaced via `Message: err.Error()`) — Cloud Run returns detailed reasons for rejected specs
- Ensure the image is pushed and accessible: `gcloud run deploy` equivalent requires the container image to exist; check `--default-repo` substitution and the `spec.template.spec.containers[0].image` value
- Grant the Cloud Run service agent access to pull from the image registry (Artifact Registry Reader role) for cross-project images
- Validate the service spec against the Cloud Run schema; common rejects are bad health-check probes, missing port config, or invalid resource limits
- Retry if the failure was transient (e.g. 429/503); check quotas in the GCP console
Example fix
# before: image not found image: my-app:latest # never pushed # after skaffold deploy --default-repo=gcr.io/my-project # renders image: gcr.io/my-project/my-app:latest
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the image exists and is pullable before deploying
func imageExists(image string) error {
name := strings.SplitN(image, ":", 2)[0]
return exec.Command("gcloud", "artifacts", "docker", "images", "describe", name).Run()
} Try / catch
if err := deployer.Deploy(ctx, out, artifacts); err != nil {
var sErr *sErrors.Error
if errors.As(err, &sErr) && sErr.Status().ErrCode == proto.StatusCode_DEPLOY_CLOUD_RUN_UPDATE_SERVICE_ERR {
msg := sErr.Status().Message
switch {
case strings.Contains(msg, "IMAGE_PULL") || strings.Contains(msg, "image"):
return fmt.Errorf("check image exists and is pullable by Cloud Run (%s)", msg)
case strings.Contains(msg, "429") || strings.Contains(msg, "503"):
time.Sleep(10 * time.Second)
return deployer.Deploy(ctx, out, artifacts) // retry transient failures
}
}
return err
} Prevention
- Push images before deploying and use --default-repo so image references resolve to a reachable registry
- Grant the Cloud Run service agent Artifact Registry Reader for cross-project images
- Validate service spec fields (probes, resources, ports) against the Cloud Run schema
- Watch quotas/limits in the region and retry on 429/503 transient errors
When it happens
Trigger: `createCall.Do()` or `replaceCall.Do()` returns an error in `deployService` — e.g. image not found/pull denied, invalid service spec rejected by the API (400), revision creation failure, quota exceeded, or conditional update conflicts.
Common situations: The image referenced in the manifest isn't pushed to a registry the project can pull from (private repo, wrong tag); `--default-repo` substitution missing so the API can't resolve the image; spec violations like missing `containers` or invalid probes; regional quota limits; IAM preventing the run service agent from pulling the image.
Related errors
- DEPLOY_CLOUD_RUN_GET_SERVICE_ERR
- StatusCode_DEPLOY_CLOUD_RUN_DELETE_SERVICE_ERR
- StatusCode_DEPLOY_CLOUD_RUN_DELETE_WORKER_POOL_ERR
- strings.Join(errMsgs, "\n") (joined helm cleanup error messa
- skaffold apply called with both Cloud Run and Kubernetes dep
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/fd07b8aebacc5958.
Report an issue: GitHub.