GoogleContainerTools/skaffold · error

StatusCode_DEPLOY_CLOUD_RUN_DELETE_SERVICE_ERR

StatusCode_DEPLOY_CLOUD_RUN_DELETE_SERVICE_ERR

Error message

unable to delete Cloud Run Service

What it means

Thrown by deleteRunService when the Cloud Run API Delete call (crclient.Projects.Locations.Services.Delete(sName).Do()) returns an error. The project/region/service resource name were resolved fine, but the API refused or failed the deletion. The underlying API error text is surfaced in the actionable error Message.

Solutions

  1. Read the embedded err.Error() in the actionable error: if 404, the service is already gone and cleanup can be re-run/ignored
  2. Verify gcloud auth and IAM: the identity needs roles/run.admin (run.services.delete)
  3. Confirm deploy.cloudrun.region matches the region the service was deployed to
  4. Retry on transient (5xx/network) failures after checking service state

Example fix

// before: deleting in wrong region
deploy:
  cloudrun:
    region: us-central1
// after: match the region used at deploy time
deploy:
  cloudrun:
    region: us-east1
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check before delete
call := crclient.Projects.Locations.Services.Get(sName)
if _, err := call.Do(); err != nil {
	if gErr, ok := err.(*googleapi.Error); ok && gErr.Code == 404 {
		return nil // already deleted, skip
	}
	return err
}

Try / catch

if _, err := delCall.Do(); err != nil {
	if gErr, ok := err.(*googleapi.Error); ok {
		switch gErr.Code {
		case 404:
			return nil // idempotent delete
		case 403:
			return fmt.Errorf("IAM: needs run.services.delete: %w", err)
		case 429, 500, 503:
			return retryWithBackoff(delCall)
		}
	}
	return err
}

Prevention

When it happens

Trigger: cleanupRun -> deleteRunService calls Projects.Locations.Services.Delete on projects/<proj>/locations/<region>/services/<name> and the API returns a non-2xx response or transport error.

Common situations: Service already deleted (404) or never existed; wrong region configured; missing run.services.delete IAM permission or expired credentials; API not enabled; transient network failures; service has a delete-blocking state (e.g. deletion already in progress).

Related errors


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

Appendix: source

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

		projectID = service.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("projects/%s/locations/%s", projectID, d.Region)
	sName := fmt.Sprintf("%s/services/%s", parent, service.Metadata.Name)
	if dryRun {
		output.Yellow.Fprintln(out, sName)
		return nil
	}

	delCall := crclient.Projects.Locations.Services.Delete(sName)
	_, err := delCall.Do()
	if err != nil {
		return sErrors.NewError(fmt.Errorf("unable to delete Cloud Run Service"), &proto.ActionableErr{
			Message: err.Error(),
			ErrCode: proto.StatusCode_DEPLOY_CLOUD_RUN_DELETE_SERVICE_ERR,
		})
	}
	return nil
}

func (d *Deployer) deleteRunJob(crclient *run.APIService, out io.Writer, dryRun bool, manifest []byte) error {
	job := &run.Job{}
	if err := k8syaml.Unmarshal(manifest, job); err != nil {
		return sErrors.NewError(fmt.Errorf("unable to unmarshal Cloud Run Job config: %w", err), &proto.ActionableErr{
			Message: err.Error(),
			ErrCode: proto.StatusCode_DEPLOY_READ_MANIFEST_ERR,
		})
	}
	var projectID string
	switch {
	case d.Project != "":

View on GitHub (pinned to a1189de023)