GoogleContainerTools/skaffold · error

StatusCode_DEPLOY_CLOUD_RUN_UPDATE_WORKER_POOL_ERR

StatusCode_DEPLOY_CLOUD_RUN_UPDATE_WORKER_POOL_ERR

Error message

error deploying Cloud Run WorkerPool: %s

What it means

deployWorkerPool finalizes by calling Workerpools.Create (new pool) or ReplaceWorkerPool (existing pool). Any error from either call is wrapped as DEPLOY_CLOUD_RUN_UPDATE_WORKER_POOL_ERR with the upstream message; the WorkerPool was not deployed.

Source

Thrown at pkg/skaffold/deploy/cloudrun/deploy.go:472

	_, 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_WORKER_POOL_ERR,
			})
		}
		// This is a new workerpool, we need to create it
		createCall := crclient.Namespaces.Workerpools.Create(parent, workerpool)
		_, err = createCall.Do()
	} else {
		replaceCall := crclient.Namespaces.Workerpools.ReplaceWorkerPool(wpName, workerpool)
		_, err = replaceCall.Do()
	}
	if err != nil {
		return nil, sErrors.NewError(fmt.Errorf("error deploying Cloud Run WorkerPool: %s", err), &proto.ActionableErr{
			Message: err.Error(),
			ErrCode: proto.StatusCode_DEPLOY_CLOUD_RUN_UPDATE_WORKER_POOL_ERR,
		})
	}
	return &resName, nil
}

func (d *Deployer) cleanupRun(ctx context.Context, out io.Writer, dryRun bool, manifests manifest.ManifestList) error {
	var errors []error
	cOptions := d.clientOptions
	if d.useGcpOptions {
		cOptions = append(cOptions, option.WithEndpoint(fmt.Sprintf("%s-run.googleapis.com", d.Region)))
		cOptions = append(gcp.ClientOptions(ctx), cOptions...)
	}
	crclient, err := run.NewService(ctx, cOptions...)
	if err != nil {
		return sErrors.NewError(fmt.Errorf("unable to create Cloud Run Client"), &proto.ActionableErr{
			Message: err.Error(),

View on GitHub (pinned to a1189de023)

Solutions

  1. Read the wrapped message for the API's specific rejection reason (usually names the invalid field)
  2. Confirm the WorkerPool API is enabled/allowlisted for the project and region
  3. Check IAM permissions for creating/updating WorkerPools
  4. Validate CPU/memory/GPU settings against Cloud Run WorkerPool limits
  5. Retry on transient 5xx errors
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check WorkerPool spec before submit
spec := workerpool.Spec.Template.Spec
if len(spec.Containers) == 0 {
    return fmt.Errorf("workerpool has no containers")
}
if spec.Containers[0].Image == "" {
    return fmt.Errorf("workerpool container image is empty")
}

Type guard

func isWPAPIRejection(err error) bool {
    var gErr *googleapi.Error
    return errors.As(err, &gErr) && gErr.Code == 400
}

Try / catch

err := deployWorkerPool(crclient, manifest, out)
if err != nil {
    var gErr *googleapi.Error
    if errors.As(err, &gErr) {
        switch {
        case gErr.Code == 400:
            log.Errorf("invalid WorkerPool spec: %s", gErr.Body)
        case gErr.Code == 403:
            return fmt.Errorf("missing WorkerPool create/update permission")
        case gErr.Code >= 500 || gErr.Code == 429:
            return retryDeploy()
        }
    }
    return err
}

Prevention

When it happens

Trigger: CreateCall.Do() or ReplaceWorkerPool.Do() returns an error: invalid WorkerPool spec (400), 403 missing permissions, quota exceeded, immutable field conflicts on replace, or network failure.

Common situations: WorkerPool feature not enabled/allowed in the project (alpha surfaces); invalid CPU/memory or container spec rejected by the API; service account lacks run.workerpools permissions; regional quota exhaustion.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/d041a059677193ee. Report an issue: GitHub.