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.

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)

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.