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
- Escape literal dollar signs as $$ so the parser treats them literally.
- Close any unclosed ${ ... } expressions and verify variable name syntax.
- 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
- Escape literal dollar signs as $$ in compose values.
- Ensure every ${ is closed by } and uses a valid variable name.
- Lint compose files for stray $ characters.
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
- template parsing error
- failed to cast to expected type
- error while interpolating
- invalid boolean
- failed to parse hook template
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)