GoogleContainerTools/skaffold · error

putting build arguments: %w

Error message

putting build arguments: %w

What it means

expandBuildArgs evaluates the caller-supplied build args map as environment-style templates (util.EvaluateEnvTemplateMap) before substituting them into ARG instructions; when a value references an unset variable or uses malformed template syntax, this error wraps the failure. Skaffold cannot resolve which files COPY depends on without concrete ARG values.

Source

Thrown at pkg/skaffold/docker/parse.go:104

func ReadCopyCmdsFromDockerfile(ctx context.Context, onlyLastImage bool, absDockerfilePath, workspace string, buildArgs map[string]*string, cfg Config) ([]FromTo, error) {
	r, err := os.ReadFile(absDockerfilePath)
	if err != nil {
		return nil, err
	}

	res, err := parser.Parse(bytes.NewReader(r))
	if err != nil {
		return nil, fmt.Errorf("parsing dockerfile %q: %w", absDockerfilePath, err)
	}

	if err := validateParsedDockerfile(bytes.NewReader(r), res); err != nil {
		return nil, fmt.Errorf("parsing dockerfile %q: %w", absDockerfilePath, err)
	}

	dockerfileLines := res.AST.Children

	if err := expandBuildArgs(dockerfileLines, buildArgs); err != nil {
		return nil, fmt.Errorf("putting build arguments: %w", err)
	}

	dockerfileLinesWithOnbuild, err := expandOnbuildInstructions(ctx, dockerfileLines, cfg)
	if err != nil {
		return nil, err
	}

	cpCmds, err := extractCopyCommands(ctx, dockerfileLinesWithOnbuild, onlyLastImage, cfg)
	if err != nil {
		return nil, fmt.Errorf("listing copied files: %w", err)
	}

	return expandSrcGlobPatterns(workspace, cpCmds)
}

func ExtractOnlyCopyCommands(absDockerfilePath string) ([]FromTo, error) {
	r, err := os.ReadFile(absDockerfilePath)
	if err != nil {

View on GitHub (pinned to a1189de023)

Solutions

  1. Set the missing environment variable in your shell/CI before invoking Skaffold
  2. Provide a default in the Dockerfile itself: ARG MYVAR=default-value
  3. Fix the template syntax in the build args (escape literal dollars as $$ or remove unbalanced braces)
  4. Move the value out of a template expression and pass it as a plain literal build arg

Example fix

// before (skaffold.yaml)
buildArgs:
  TAG: ${GIT_TAG}
// after
buildArgs:
  TAG: ${GIT_TAG:-dev}
Defensive patterns

Strategy: validation

Validate before calling

func argsResolvable(buildArgs map[string]*string) error {
    for k, v := range buildArgs {
        if v == nil { continue }
        if _, err := shell.Expand(*v, os.Getenv); err != nil {
            return fmt.Errorf("build arg %q has invalid expansion: %w", k, err)
        }
    }
    return nil
}
// or pre-expand: for k, v := range buildArgs { if v != nil { e := os.ExpandEnv(*v); buildArgs[k] = &e } }

Type guard

func hasBalancedTemplate(s string) bool {
    return strings.Count(s, "${") == strings.Count(s, "}")
}

Try / catch

if err := skaffoldEval(buildArgs); err != nil {
    if strings.Contains(err.Error(), "unable to evaluate build args") {
        return fmt.Errorf("unset/malformed build arg; provide env var or default: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: ReadCopyCmdsFromDockerfile called with buildArgs containing '${VAR}' where VAR is not set in the process environment, or containing invalid shell/template expansion syntax (unbalanced '${', bad default expansions like '${VAR:x}').

Common situations: CI environments missing an env var that exists on a developer machine; skaffold.yaml build args copied from a docker-compose file with unsupported interpolation syntax; a renamed environment variable upstream; quoting mistakes in skaffold.yaml that swallow a '$'.

Related errors


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