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

  1. Validate the template syntax: balance {{ }} and use supported functions.
  2. Use the built-in table/json/raw formats instead of a custom template if unsure.
  3. 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

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

Related errors


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)