GoogleContainerTools/skaffold · error
getting render output path: %w
Error message
getting render output path: %w
What it means
Before creating the renderer, `NewForConfig` resolves the hydration directory (where rendered k8s manifests are written, default `.kpt-pipeline`) via `util.GetHydrationDir`. This wraps failures to compute or create that directory — filesystem path errors or mkdir permission failures.
Source
Thrown at pkg/skaffold/runner/new.go:79
sourceDependencies := graph.NewSourceDependenciesCache(runCtx, store, g)
isLocalImage := func(imageName string) (bool, error) {
return isImageLocal(runCtx, imageName)
}
// Always add skaffold-specific labels, except during `skaffold render`
labeller := label.NewLabeller(runCtx.AddSkaffoldLabels(), runCtx.CustomLabels(), runCtx.GetRunID())
tester, err := getTester(ctx, runCtx, isLocalImage)
if err != nil {
endTrace(instrumentation.TraceEndError(err))
return nil, fmt.Errorf("creating tester: %w", err)
}
var deployer deploy.Deployer
hydrationDir, err := util.GetHydrationDir(runCtx.Opts, runCtx.WorkingDir, true, isKptRendererOrDeployerUsed(runCtx.Pipelines))
if err != nil {
return nil, fmt.Errorf("getting render output path: %w", err)
}
renderer, err := GetRenderer(ctx, runCtx, hydrationDir, labeller.Labels(), runCtx.UsingLegacyHelmDeploy())
if err != nil {
endTrace(instrumentation.TraceEndError(err))
return nil, fmt.Errorf("creating renderer: %w", err)
}
deployer, err = GetDeployer(ctx, runCtx, labeller, hydrationDir, runCtx.UsingLegacyHelmDeploy())
if err != nil {
endTrace(instrumentation.TraceEndError(err))
return nil, fmt.Errorf("creating deployer: %w", err)
}
rOpts := platform.ResolverOpts{
KubeContext: runCtx.KubeContext,
CliPlatformsSelection: runCtx.Opts.Platforms,
CheckClusterNodePlatforms: runCtx.CheckClusterNodePlatforms(),
DisableMultiPlatformBuild: runCtx.DisableMultiPlatformBuild(),View on GitHub (pinned to a1189de023)
Solutions
- Ensure the `--hydration-dir` path's parent is writable (`ls -ld`, check permissions).
- Confirm the hydration dir path is not an existing regular file; remove or rename it.
- If not using kpt, no hydration dir is needed — check why a kpt renderer/deployer was selected (skaffold.yaml renderer/deployer config).
- In CI, use `--assume-yes=true` to skip the interactive non-empty-dir prompt that can otherwise hang or exit.
Example fix
// CI command before skaffold render --hydration-dir /ro-mount/.kpt-pipeline // after skaffold render --hydration-dir /tmp/.kpt-pipeline --assume-yes=true
Defensive patterns
Strategy: validation
Validate before calling
func hydrationDirReady(dir string) error {
st, err := os.Stat(dir)
if err == nil && !st.IsDir() {
return fmt.Errorf("%s exists and is not a directory", dir)
}
return os.MkdirAll(dir, 0o755)
} Try / catch
runner, err := runner.NewForConfig(runCtx)
if err != nil {
if strings.Contains(err.Error(), "getting render output path") {
return fmt.Errorf("hydration dir unusable (permissions? file conflict?): %w", err)
}
return err
} Prevention
- Point --hydration-dir at a writable location (e.g. /tmp in containers).
- Never let the hydration dir path collide with a regular file.
- Use --assume-yes=true in non-interactive CI to skip prompts.
- Check disk space and mount permissions in CI images.
When it happens
Trigger: Using a kpt renderer/deployer while `filepath.Abs(opts.HydrationDir)` fails, or `os.MkdirAll(hydrationDir)` fails because the parent directory is read-only, the path exists as a file, or the disk is full.
Common situations: Running `skaffold dev`/`render` with `--hydration-dir` inside a read-only mount; `--hydration-dir` colliding with an existing regular file; restricted CI container filesystems.
Related errors
- writing %q to %q: %w
- reading .dockerignore: %w
- walking workspace: %w
- unable to stat file %q: %w
- failed to create directory: %v
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/4c9b32581def6e8b.
Report an issue: GitHub.