argoproj/argo-workflows · error

additional headers must be colon(:)-separated

Error message

additional headers must be colon(:)-separated: %s

What it means

parseHeaders converts strings like "Key:Value" into an http.Header by splitting on ":" and requiring an odd number of resulting segments (len%2==1) — i.e. exactly one colon separating key from value (values themselves may contain colons but not keys). If a header string doesn't match, it refuses with this error. It is used by the HTTP1 facade for extra headers passed to requests and event streams.

Solutions

  1. Format each header as exactly "Name:Value" with one colon: --additional-header 'X-Foo:Bar'
  2. Repeat the flag once per header instead of combining them in one string
  3. Check shell quoting so the colon/value survive (quote the argument if it contains spaces or colons in the value)

Example fix

// before
--additional-header X-Trace-Id
// after
--additional-header X-Trace-Id:abc123
Defensive patterns

Strategy: validation

Validate before calling

func validateAdditionalHeaders(headers []string) error {
    for _, h := range headers {
        parts := strings.Split(h, ":")
        if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
            return fmt.Errorf("header %q must be exactly 'Name:Value'", h)
        }
    }
    return nil
}

Try / catch

headers := []string{"X-Trace-Id:abc"}
if err := validateAdditionalHeaders(headers); err != nil {
    return err
}
// pass to client; also wrap calls that use them:
if err != nil && strings.Contains(err.Error(), "colon(:)-separated") {
    return fmt.Errorf("check --additional-header format 'Name:Value': %w", err)
}

Prevention

When it happens

Trigger: Passing a header string to the HTTP1 client's additional-headers option (e.g. the CLI's --additional-header flag or h.headers in pkg/apiclient/http1) that contains no colon, more than one key-colon pair, or trailing whitespace forms like "Key:" with no value — e.g. --additional-header Authorization (missing ':token').

Common situations: Forgetting the value after the colon ("X-Trace-Id:"); putting the colon in the wrong place or quoting wrongly so the shell strips it; trying to pass multiple headers in one string instead of repeating the flag.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/f322d8479582459c. Report an issue: GitHub.

Appendix: source

Thrown at pkg/apiclient/http1/facade.go:218

	if r.StatusCode == http.StatusOK {
		return nil
	}
	x := &struct {
		Code    codes.Code `json:"code"`
		Message string     `json:"message"`
	}{}
	if err := json.NewDecoder(r.Body).Decode(x); err == nil {
		return status.Error(x.Code, x.Message)
	}
	return status.Error(codes.Internal, fmt.Sprintf(": %v", r))
}

func parseHeaders(headerStrings []string) (http.Header, error) {
	headers := http.Header{}
	for _, kv := range headerStrings {
		items := strings.Split(kv, ":")
		if len(items)%2 == 1 {
			return nil, fmt.Errorf("additional headers must be colon(:)-separated: %s", kv)
		}
		headers.Add(items[0], items[1])
	}
	return headers, nil
}

View on GitHub (pinned to 35bff19146)