GoogleContainerTools/skaffold · error

DEPLOY_READ_MANIFEST_ERR

DEPLOY_READ_MANIFEST_ERR

Error message

unable to unmarshal Cloud Run Service config: %w

What it means

Before deploying, `deployToCloudRun` parses the rendered manifest as a Kubernetes-style unstructured object to determine the Cloud Run resource kind. If `k8syaml.Unmarshal` fails on the manifest bytes, the error is wrapped as 'unable to unmarshal Cloud Run Service config: %w' with code DEPLOY_READ_MANIFEST_ERR.

Source

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

	return d.monitor
}
func (d *Deployer) deployToCloudRun(ctx context.Context, out io.Writer, manifest []byte) 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(),
			ErrCode: proto.StatusCode_DEPLOY_GET_CLOUD_RUN_CLIENT_ERR,
		})
	}
	// figure out which type we have:
	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,
		})
	}
	var resName *RunResourceName
	switch {
	case resource.GetAPIVersion() == "serving.knative.dev/v1" && resource.GetKind() == "Service":
		resName, err = d.deployService(crclient, manifest, out)
		// the accessor only supports services. Jobs don't run by themselves so port forwarding doesn't make sense.
		if resName != nil {
			d.accessor.AddResource(*resName)
		}
	case resource.GetAPIVersion() == "run.googleapis.com/v1" && resource.GetKind() == "Job":
		resName, err = d.deployJob(crclient, manifest, out)
	case resource.GetAPIVersion() == "run.googleapis.com/v1" && resource.GetKind() == "WorkerPool":
		resName, err = d.deployWorkerPool(crclient, manifest, out)
	default:
		err = sErrors.NewError(fmt.Errorf("unsupported Kind for Cloud Run Deployer: %s/%s", resource.GetAPIVersion(), resource.GetKind()),

View on GitHub (pinned to a1189de023)

Solutions

  1. Validate the manifest with `skaffold render` and run the output through `kubectl apply --dry-run=client` or a YAML linter to find the syntax problem
  2. Fix the YAML syntax error reported in the wrapped `%w` message (line/column are usually included)
  3. Ensure each artifact renders a single Cloud Run manifest document (split multi-doc files)
  4. If using kustomize/helm, fix templates that emit empty/invalid documents for this resource

Example fix

# before (manifest.yaml)
service:
  metadata
    name: broken   # missing colon
# after
service:
  metadata:
    name: fixed
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate rendered manifests before deploying
func validateYAML(manifest []byte) error {
	var obj map[string]interface{}
	return yaml.Unmarshal(manifest, &obj)
}
// in CI: skaffold render | yamllint - && skaffold render | kubectl apply --dry-run=client -f -

Try / catch

if err := deployer.Deploy(ctx, out, artifacts); err != nil {
	var sErr *sErrors.Error
	if errors.As(err, &sErr) && sErr.Status().ErrCode == proto.StatusCode_DEPLOY_READ_MANIFEST_ERR {
		return fmt.Errorf("manifest is not valid for Cloud Run (%s): run 'skaffold render' and lint the output", sErr.Status().Message)
	}
	return err
}

Prevention

When it happens

Trigger: `k8syaml.Unmarshal(manifest, resource)` returns an error in `deployToCloudRun` — the rendered Cloud Run manifest (possibly from `skaffold render` output, multi-doc yaml, kustomize, or Helm) is not valid YAML or not parseable as an object.

Common situations: Hand-edited manifests with indentation/typo errors; a manifest containing multiple YAML documents where skaffold expects one; templates that render empty or non-object output; using a renderer (kustomize/helm) whose output includes non-Cloud-Run scaffolding.

Related errors


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