jaegertracing/jaeger · error
ai.agent_headers: %w
Error message
ai.agent_headers: %w
What it means
This error wraps the failure of AgentHeaders.Validate() during the jaegerquery AI extension config validation. MapList (the wire type for headers) permits repeated names, so a config with two entries for the same header name would silently keep only one value at runtime; validation rejects the config up front so the operator knows which setting is broken via the "ai.agent_headers:" prefix.
Source
Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/flags.go:168
// (see the AIConfig type-level comment) so by the time Validate runs the
// caller's struct already has sensible values for any field they omitted.
func (c *AIConfig) Validate() error {
if c.AgentURL == "" && !c.MCP.HasValue() {
return errors.New("ai requires agent_url (AI chat) or mcp (telemetry MCP tools)")
}
if c.MaxRequestBodySize <= 0 {
return errors.New("ai.max_request_body_size must be a positive integer")
}
if c.HealthCheckInterval < 0 {
return errors.New("ai.health_check_interval must not be negative (0 disables the health checker)")
}
if c.HealthCheckInterval > 0 && c.HealthCheckTimeout <= 0 {
return errors.New("ai.health_check_timeout must be positive when health_check_interval is positive")
}
// MapList permits repeated names on the wire; a duplicated header would
// silently keep only one value, so reject it here rather than guess which.
if err := c.AgentHeaders.Validate(); err != nil {
return fmt.Errorf("ai.agent_headers: %w", err)
}
// MCPConfig.Validate is reached by the collector's config walk on its own,
// the same way OTLPProxyConfig's is; delegating to it here would only
// duplicate the check and drop the "mcp:" path segment from the message.
return nil
}
// resolveMCPBaseURL returns the base URL the gateway announces for the turn-scoped
// MCP endpoint, or "" to announce no HTTP transport. An explicit base_url always
// wins. Otherwise the gateway infers its own loopback address, which requires every
// leg of the round trip to hold:
//
// - The sidecar must be co-located: AgentURL is a loopback address, so the
// sidecar shares this network namespace and its "localhost" is ours.
// - The query server must actually be listening on loopback: a wildcard bind
// (":16686", "0.0.0.0", "::") or a loopback bind. Bound to one specific
// interface, say "10.0.0.5:16686", nothing answers on loopback.
// - TLS must be off. A server certificate carries a SAN for the name operatorsView on GitHub (pinned to 806f444784)
Solutions
- Remove the duplicate header entry from ai.agent_headers in your jaeger-query config, keeping the single correct value.
- If you need multiple values for one header, combine them into one entry (e.g. comma-joined value) where the target system allows it.
- Review how the config is assembled (env overlays, helm values, templates) to find what injects the duplicate.
Example fix
// before
agent_headers:
- name: Authorization
value: "Bearer x"
- name: Authorization
value: "Bearer y"
// after
agent_headers:
- name: Authorization
value: "Bearer x" Defensive patterns
Strategy: validation
Validate before calling
names := map[string]bool{}
for _, h := range cfg.AgentHeaders {
if names[h.Name] {
return fmt.Errorf("duplicate agent header: %s", h.Name)
}
names[h.Name] = true
} Prevention
- Deduplicate header lists when merging config fragments (helm/kustomize overlays).
- Lint config for repeated header names in CI before deploy.
- Keep a single source of truth for auth headers instead of appending per environment.
When it happens
Trigger: Starting jaeger-all-in-one or jaeger-query with an AI config whose agent_headers map/list contains two entries with the same header name, e.g. agent_headers: [{name: Authorization, value: a}, {name: Authorization, value: b}].
Common situations: Operators merging YAML config fragments (e.g. base + overlay) so the same header appears twice; copy-pasting header blocks when adding auth and custom tracing headers; templating tools emitting duplicate keys.
Related errors
- no sampling strategy provider specified, expecting 'adaptive
- only one sampling strategy provider can be specified, 'adapt
- reload interval must be a positive value, or zero to disable
- unknown metrics backend specified
- CalculationInterval and AggregationBuckets must be greater t
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/d9fa1076c83a87f1.
Report an issue: GitHub.