GoogleContainerTools/skaffold · error
StatusCode_DEPLOY_READ_MANIFEST_ERR
StatusCode_DEPLOY_READ_MANIFEST_ERR
Error message
unable to unmarshal Cloud Run Service config: %w
What it means
During cleanup, deleteRunService unmarshals each rendered Cloud Run Service manifest into run.Service. If k8syaml.Unmarshal fails (malformed YAML or fields incompatible with run.Service), the service cannot be deleted and DEPLOY_READ_MANIFEST_ERR is returned, aborting cleanup of that resource.
Source
Thrown at pkg/skaffold/deploy/cloudrun/deploy.go:526
}
case tpe == typeWorkerPool:
err := d.deleteRunWorkerPool(crclient, out, dryRun, manifest)
if err != nil {
errors = append(errors, err)
}
}
}
if len(errors) != 0 {
// TODO: is there a good way to report all of the errors?
return errors[0]
}
return nil
}
func (d *Deployer) deleteRunService(crclient *run.APIService, out io.Writer, dryRun bool, manifest []byte) error {
service := &run.Service{}
if err := k8syaml.Unmarshal(manifest, service); 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,
})
}
var projectID string
switch {
case d.Project != "":
projectID = d.Project
case service.Metadata.Namespace != "":
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,
})
}View on GitHub (pinned to a1189de023)
Solutions
- Re-render the manifests (`skaffold render`) to regenerate clean output and clear stale state
- Validate the YAML syntax and fix indentation/typing issues
- Ensure the manifest is a Cloud Run Service (kind: Service, run.googleapis.com) matching the v1 schema
- Manually delete the resource with `gcloud run services delete` if cleanup remains blocked
Example fix
// before (ports typed wrong) containers: - image: img:latest ports: "8080" // after containers: - image: img:latest ports: - containerPort: 8080
Defensive patterns
Strategy: validation
Validate before calling
func validateServiceManifest(manifest []byte) error {
var m map[string]interface{}
if err := yaml.Unmarshal(manifest, &m); err != nil {
return fmt.Errorf("invalid YAML: %w", err)
}
if m["kind"] != "Service" {
return fmt.Errorf("expected kind Service, got %v", m["kind"])
}
return nil
} Type guard
func isCloudRunService(m map[string]interface{}) bool {
kind, _ := m["kind"].(string)
return kind == "Service"
} Try / catch
err := deployer.Cleanup(ctx, out)
if err != nil {
var actionErr *sErrors.Error
if errors.As(err, &actionErr) && actionErr.ErrCode == proto.StatusCode_DEPLOY_READ_MANIFEST_ERR {
// re-render manifests or fall back to `gcloud run services delete`
}
return err
} Prevention
- Re-run `skaffold render` if cached rendered manifests look stale
- Keep rendered manifests unmodified after generation
- Add CI validation of rendered output before deploy/cleanup
- Fall back to `gcloud run services delete` when cleanup is blocked by a corrupt manifest
When it happens
Trigger: deleteRunService calls k8syaml.Unmarshal(manifest, service) on manifests fetched from skaffold's rendered output or a stored Cloud Run state file that is corrupted, truncated, or has wrong-typed fields for run.Service.
Common situations: Corrupted/truncated rendered-manifests cache between runs; a manifest edited after render; wrong kind captured for a Service slot; schema drift causing type mismatches (e.g. ports as strings).
Related errors
- DEPLOY_READ_MANIFEST_ERR
- invalid local-registry-hosting ConfigMap
- strings.Join(errMsgs, "\n") (joined helm cleanup error messa
- skaffold apply called with both Cloud Run and Kubernetes dep
- CONFIG_ZERO_FOUND_ERR
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/b22aa550e9d9844b.
Report an issue: GitHub.