GoogleContainerTools/skaffold · error

failed to execute container %s hook %d for artifact %q: %w

Error message

failed to execute container %s hook %d for artifact %q: %w

What it means

Skaffold also supports container hooks — commands executed inside the running artifact's container during sync. If such a hook's run() returns any error (Skip handling doesn't apply here), run wraps it with the phase, 1-based hook index, artifact image name, and underlying cause, aborting the sync.

Source

Thrown at pkg/skaffold/hooks/sync.go:97

		output.Default.Fprintf(out, "Starting %s hooks for artifact %q...\n", phase, r.imageName)
	}
	env := r.getEnv()
	for i, h := range hooks {
		if h.HostHook != nil {
			hook := hostHook{*h.HostHook, env}
			if err := hook.run(ctx, nil, out); err != nil && !errors.Is(err, &Skip{}) {
				return fmt.Errorf("failed to execute host %s hook %d for artifact %q: %w", phase, i+1, r.imageName, err)
			}
		} else if h.ContainerHook != nil {
			hook := containerHook{
				cfg:        *h.ContainerHook,
				cli:        r.cli,
				selector:   runningImageSelector(r.imageRef),
				namespaces: r.namespaces,
				formatter:  r.formatter,
			}
			if err := hook.run(ctx, out); err != nil {
				return fmt.Errorf("failed to execute container %s hook %d for artifact %q: %w", phase, i+1, r.imageName, err)
			}
		}
	}
	if len(hooks) > 0 {
		output.Default.Fprintf(out, "Completed %s hooks for artifact %q\n", phase, r.imageName)
	}
	return nil
}

View on GitHub (pinned to a1189de023)

Solutions

  1. Verify the command exists inside the image (docker run <img> <cmd>) and add it to the Dockerfile if missing
  2. Check the wrapped error: if it's an exec/pod error, ensure the pod is running and the namespaces list matches where the workload runs
  3. Use sh -c wrapping and correct quoting; for distroless images switch to a host hook or copy a shell in
  4. Run with --verbosity=debug to see the exact exec command and pod it targeted

Example fix

// before (skaffold.yaml, distroless image)
sync:
  hooks:
    after:
      - container:
          command: ["sh", "-c", "touch /tmp/reload"]
// after (use a host hook instead)
sync:
  hooks:
    after:
      - host:
          command: ["kubectl", "exec", "deploy/my-app", "--", "kill", "-HUP", "1"]
Defensive patterns

Strategy: retry

Validate before calling

// ensure the target pods are running and the command exists in the image:
kubectl get pods -n <ns> -l <selector> --field-selector=status.phase=Running
docker run --rm <image> <hook_cmd> --help  # proves the binary is in the image

Try / catch

if err := syncRunner.RunPostHooks(ctx, out); err != nil {
    if strings.Contains(err.Error(), "failed to execute container") {
        // often a transient exec/pod-readiness issue: retry once after a short wait
        time.Sleep(2 * time.Second)
        return syncRunner.RunPostHooks(ctx, out)
    }
    return err
}

Prevention

When it happens

Trigger: A containerHook command fails inside the running container while RunPreHooks/RunPostHooks process sync hooks for the artifact: command not found in the container image, non-zero exit, kubectl exec/transport error reaching the pod, or the container/pod not running in any of the target namespaces.

Common situations: Command present on host but absent in the slim container image; hook requires a shell not installed (distroless images); pod not yet ready so exec fails; RBAC/namespace mismatch preventing exec.

Related errors


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