docker/cli · error
failed to parse template
Error message
failed to parse template: %w
What it means
Returned by list.go:87 when templates.Parse fails on the value of `docker ps --format`. The format string is parsed as a Go text/template every time --format is provided so that errors surface consistently. The wrapped %w is the template parse error.
Solutions
- Validate the template syntax: balance {{ }} and use supported functions.
- Use the built-in table/json/raw formats instead of a custom template if unsure.
- Test incrementally starting from a known-good template like {{.ID}} {{.Names}}.
Example fix
# before
docker ps --format "{{.ID {{.Names}}"
# after
docker ps --format "{{.ID}} {{.Names}}" Defensive patterns
Strategy: validation
Validate before calling
import "text/template"
if _, err := template.New("f").Funcs(dockerFuncs).Parse(formatStr); err != nil {
return fmt.Errorf("invalid --format template: %w", err)
} Try / catch
// Parse failures are deterministic; fix the template rather than retry.
if err != nil && strings.Contains(err.Error(), "failed to parse template") {
/* fall back to default formatting */
} Prevention
- Test custom --format strings before scripting them.
- Prefer built-in table/json formats when possible.
- Balance every {{ with a }}.
When it happens
Trigger: `docker ps --format` with a malformed Go template: unbalanced `{{ }}`, unknown function, bad pipeline, or a syntax error.
Common situations: Typo in a format template, copy-paste of a format meant for another command, or a template using a function not registered in the Docker template engine.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to execute template
- invalid pull option: ' ': must be one of , or
- invalid detach keys ( )
- placement preference must be of the format
- invalid credential spec: value must be prefixed with…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/dc68b18a2c520b7e.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/list.go:87
}
func buildContainerListOptions(options *psOptions) (client.ContainerListOptions, error) {
listOptions := client.ContainerListOptions{
All: options.all,
Limit: options.last,
Size: options.size,
Filters: options.filter.Value(),
}
if options.nLatest && options.last == -1 {
listOptions.Limit = 1
}
// always validate template when `--format` is used, for consistency
if len(options.format) > 0 {
tmpl, err := templates.Parse(options.format)
if err != nil {
return client.ContainerListOptions{}, fmt.Errorf("failed to parse template: %w", err)
}
optionsProcessor := formatter.NewContainerContext()
// This shouldn't error out but swallowing the error makes it harder
// to track down if preProcessor issues come up.
if err := tmpl.Execute(io.Discard, optionsProcessor); err != nil {
return client.ContainerListOptions{}, fmt.Errorf("failed to execute template: %w", err)
}
// if `size` was not explicitly set to false (with `--size=false`)
// and `--quiet` is not set, request size if the template requires it
if !options.quiet && !listOptions.Size && !options.sizeChanged {
// The --size option isn't set, but .Size may be used in the template.
// Parse and execute the given template to detect if the .Size field is
// used. If it is, then automatically enable the --size option. See #24696
//
// Only requesting container size information when needed is an optimization,View on GitHub (pinned to 4f84911bfe)