docker/cli · error · invalidParameterErr

failed to parse custom headers from

Error message

failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs

What it means

Returned by withCustomHeadersFromEnv() when the DOCKER_CUSTOM_HEADERS environment variable is set but its value cannot be parsed as a CSV record of header pairs. The function constructs a csv.Reader over the value (cli_options.go:176-177) and treats any csv.Read error as a hard invalidParameter failure. CSV parsing fails on issues like unbalanced quotes or a stray quote inside an unquoted field.

Solutions

  1. Format DOCKER_CUSTOM_HEADERS as comma-separated key=value pairs: 'X-Custom=value,Another=otherval'.
  2. If a value contains a comma, wrap the entire pair in double quotes: '"Cache-Control=max-age=0, no-cache"'.
  3. Ensure all double-quotes are balanced; escape literal quotes by doubling them inside a quoted field per RFC 4180.
  4. Validate the value with a quick CSV parse before exporting it in scripts.

Example fix

// before
export DOCKER_CUSTOM_HEADERS='X-Custom="header-value'   # unbalanced quote -> CSV error
// after
export DOCKER_CUSTOM_HEADERS='X-Custom=header-value,Other=ok'
Defensive patterns

Strategy: validation

Validate before calling

// Validate DOCKER_CUSTOM_HEADERS parses as CSV before exporting.
func validateCustomHeadersCSV(value string) error {
    r := csv.NewReader(strings.NewReader(value))
    if _, err := r.Read(); err != nil {
        return fmt.Errorf("DOCKER_CUSTOM_HEADERS is not valid CSV of key=value pairs: %w", err)
    }
    return nil
}

Try / catch

if _, err := command.WithCustomHeadersFromEnv(); err != nil {
    // hint: balance quotes, wrap comma-containing values in quotes, RFC 4180 escaping
}

Prevention

When it happens

Trigger: Setting DOCKER_CUSTOM_HEADERS to a value with CSV-structural problems: an unbalanced double-quote (e.g. 'X-Foo="bar'), an embedded quote in an unquoted field, or a record that the CSV reader rejects. The parser expects comma-separated key=value tokens, optionally quoted as a whole CSV field.

Common situations: Users quoting only one side of a header value, pasting a header value that itself contains a comma without wrapping the whole key=value in quotes, or copy-pasting JSON-like values that contain stray quotes.

Understand the failure class

Related errors


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

Appendix: source

Thrown at cli/command/cli_options.go:179

// environment variable is the equivalent to the HttpHeaders field in the
// configuration file.
//
// WARNING: If both config and environment-variable are set, the environment-
// variable currently overrides all headers set in the configuration file.
// This behavior may change in a future update, as we are considering the
// environment-variable to be appending to existing headers (and to only
// override headers with the same name).
//
// TODO(thaJeztah): this is a client Option, and should be moved to the client. It is non-exported for that reason.
func withCustomHeadersFromEnv() (client.Opt, error) {
	value := os.Getenv(envOverrideHTTPHeaders)
	if value == "" {
		return nil, nil
	}
	csvReader := csv.NewReader(strings.NewReader(value))
	fields, err := csvReader.Read()
	if err != nil {
		return nil, invalidParameter(fmt.Errorf(
			"failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs",
			envOverrideHTTPHeaders,
		))
	}
	if len(fields) == 0 {
		return nil, nil
	}

	env := map[string]string{}
	for _, kv := range fields {
		k, v, hasValue := strings.Cut(kv, "=")

		// Only strip whitespace in keys; preserve whitespace in values.
		k = strings.TrimSpace(k)

		if k == "" {
			return nil, invalidParameter(fmt.Errorf(
				`failed to set custom headers from %s environment variable: value contains a key=value pair with an empty key: '%s'`,

View on GitHub (pinned to 4f84911bfe)