GoogleContainerTools/skaffold · error

StatusCode_DEPLOY_CLOUD_RUN_DELETE_WORKER_POOL_ERR

StatusCode_DEPLOY_CLOUD_RUN_DELETE_WORKER_POOL_ERR

Error message

unable to delete Cloud Run WorkerPool

What it means

Thrown by deleteRunWorkerPool when the WorkerPools API delete call (crclient.Namespaces.Workerpools.Delete(sName).Do()) fails. Resource name construction succeeded, but the API returned an error, which is embedded verbatim in the actionable error message.

Source

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

		projectID = workerpool.Metadata.Namespace
	default:
		// no project specified, we don't know what to delete.
		return sErrors.NewError(fmt.Errorf("unable to determine Google Cloud Project"), &proto.ActionableErr{
			Message: "No Google Cloud Project found in Cloud Run manifest or Skaffold Manifest.",
			ErrCode: proto.StatusCode_DEPLOY_READ_MANIFEST_ERR,
		})
	}
	parent := fmt.Sprintf("namespaces/%s", projectID)
	sName := fmt.Sprintf("%s/workerpools/%s", parent, workerpool.Metadata.Name)
	if dryRun {
		output.Yellow.Fprintln(out, sName)
		return nil
	}

	delCall := crclient.Namespaces.Workerpools.Delete(sName)
	_, err := delCall.Do()
	if err != nil {
		return sErrors.NewError(fmt.Errorf("unable to delete Cloud Run WorkerPool"), &proto.ActionableErr{
			Message: err.Error(),
			ErrCode: proto.StatusCode_DEPLOY_CLOUD_RUN_DELETE_WORKER_POOL_ERR,
		})
	}
	return nil
}

func getTypeFromManifest(manifest []byte) (string, error) {
	resource := &unstructured.Unstructured{}
	if err := k8syaml.Unmarshal(manifest, resource); err != nil {
		return "", sErrors.NewError(fmt.Errorf("unable to unmarshal Cloud Run Service config: %w", err), &proto.ActionableErr{
			Message: err.Error(),
			ErrCode: proto.StatusCode_DEPLOY_READ_MANIFEST_ERR,
		})
	}
	switch {
	case resource.GetAPIVersion() == "serving.knative.dev/v1" && resource.GetKind() == "Service":
		return typeService, nil

View on GitHub (pinned to a1189de023)

Solutions

  1. Check the embedded API error: 404 means nothing to delete — safe to continue
  2. Ensure the Cloud Run Worker Pool API is enabled and the caller has delete permissions (roles/run.admin)
  3. Confirm the project and workerpool name in the constructed resource name are correct
  4. Retry transient 5xx/network failures with backoff
Defensive patterns

Strategy: try-catch

Validate before calling

call := crclient.Namespaces.Workerpools.Get(sName)
if _, err := call.Do(); err != nil {
	if gErr, ok := err.(*googleapi.Error); ok && gErr.Code == 404 {
		return nil // already gone
	}
	return err
}

Try / catch

if _, err := delCall.Do(); err != nil {
	var gErr *googleapi.Error
	if errors.As(err, &gErr) {
		switch {
		case gErr.Code == 404:
			return nil // idempotent
		case gErr.Code == 403:
			return fmt.Errorf("missing WorkerPool delete permission / API not enabled: %w", err)
		case gErr.Code == 429 || gErr.Code >= 500:
			return retryWithBackoff(delCall)
		}
	}
	return err
}

Prevention

When it happens

Trigger: cleanupRun -> deleteRunWorkerPool calls Namespaces.Workerpools.Delete on namespaces/<proj>/workerpools/<name> and the API returns non-2xx or a transport error.

Common situations: WorkerPool already deleted or never created (404); missing IAM permission for the (alpha) WorkerPool API; WorkerPool API not enabled/available in the project or region; transient network failures.

Related errors


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