docker/cli · error

invalid interpolation format for

Error message

invalid interpolation format for %s: %#v; you may need to escape any $ with another $

What it means

Returned by newPathError when the template engine raises an *template.InvalidTemplateError, meaning the interpolation expression is syntactically malformed (interpolation.go:106-109). Common forms are an unclosed ${, a stray $, or unsupported brace syntax; the message suggests escaping $ as $$.

Solutions

  1. Escape literal dollar signs as $$ so the parser treats them literally.
  2. Close any unclosed ${ ... } expressions and verify variable name syntax.
  3. If the value is not meant to be interpolated, replace $ with $$.

Example fix

# before
environment:
  PASSWORD: pa$$word!
# after
environment:
  PASSWORD: pa$$word!  # literal $ preserved
Defensive patterns

Strategy: validation

Validate before calling

// Detect unescaped $ / malformed templates before interpolation.
var dollarRe = regexp.MustCompile(`\$\{[^}]*$|\$\{`) // very rough: unclosed brace
func warnBadTemplates(values []string) {
    for _, v := range values {
        if dollarRe.MatchString(v) {
            log.Warnf("possible malformed interpolation in %q; escape literal $ as $$", v)
        }
    }
}

Prevention

When it happens

Trigger: A compose value contains a malformed interpolation such as ${VAR, ${VAR without closing brace, or an unescaped $ followed by non-template text. Substitute returns *template.InvalidTemplateError, which newPathError reformats.

Common situations: Including a literal dollar sign (e.g. a password, a shell var) without escaping as $$; partial copy of a template; editor stripped a closing brace; referencing $$ for non-interpolation purposes.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/1c1b60468527e840. Report an issue: GitHub.

Appendix: source

Thrown at cli/compose/interpolation/interpolation.go:107

			interpolatedElem, err := recursiveInterpolate(elem, path.Next(PathMatchList), opts)
			if err != nil {
				return nil, err
			}
			out[i] = interpolatedElem
		}
		return out, nil

	default:
		return value, nil
	}
}

func newPathError(path Path, err error) error {
	switch err := err.(type) {
	case nil:
		return nil
	case *template.InvalidTemplateError:
		return fmt.Errorf(
			"invalid interpolation format for %s: %#v; you may need to escape any $ with another $",
			path, err.Template)
	default:
		return fmt.Errorf("error while interpolating %s: %w", path, err)
	}
}

const pathSeparator = "."

// PathMatchAll is a token used as part of a Path to match any key at that level
// in the nested structure
const PathMatchAll = "*"

// PathMatchList is a token used as part of a Path to match items in a list
const PathMatchList = "[]"

// Path is a dotted path of keys to a value in a nested mapping structure. A *
// section in a path will match any key in the mapping structure.

View on GitHub (pinned to 4f84911bfe)