{"record":{"id":"d9fa1076c83a87f1","repo":"jaegertracing/jaeger","slug":"ai-agent-headers-w","errorCode":null,"errorMessage":"ai.agent_headers: %w","messagePattern":"ai\\.agent_headers: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/jaeger/internal/extension/jaegerquery/internal/flags.go","lineNumber":168,"sourceCode":"// (see the AIConfig type-level comment) so by the time Validate runs the\n// caller's struct already has sensible values for any field they omitted.\nfunc (c *AIConfig) Validate() error {\n\tif c.AgentURL == \"\" && !c.MCP.HasValue() {\n\t\treturn errors.New(\"ai requires agent_url (AI chat) or mcp (telemetry MCP tools)\")\n\t}\n\tif c.MaxRequestBodySize <= 0 {\n\t\treturn errors.New(\"ai.max_request_body_size must be a positive integer\")\n\t}\n\tif c.HealthCheckInterval < 0 {\n\t\treturn errors.New(\"ai.health_check_interval must not be negative (0 disables the health checker)\")\n\t}\n\tif c.HealthCheckInterval > 0 && c.HealthCheckTimeout <= 0 {\n\t\treturn errors.New(\"ai.health_check_timeout must be positive when health_check_interval is positive\")\n\t}\n\t// MapList permits repeated names on the wire; a duplicated header would\n\t// silently keep only one value, so reject it here rather than guess which.\n\tif err := c.AgentHeaders.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"ai.agent_headers: %w\", err)\n\t}\n\t// MCPConfig.Validate is reached by the collector's config walk on its own,\n\t// the same way OTLPProxyConfig's is; delegating to it here would only\n\t// duplicate the check and drop the \"mcp:\" path segment from the message.\n\treturn nil\n}\n\n// resolveMCPBaseURL returns the base URL the gateway announces for the turn-scoped\n// MCP endpoint, or \"\" to announce no HTTP transport. An explicit base_url always\n// wins. Otherwise the gateway infers its own loopback address, which requires every\n// leg of the round trip to hold:\n//\n//   - The sidecar must be co-located: AgentURL is a loopback address, so the\n//     sidecar shares this network namespace and its \"localhost\" is ours.\n//   - The query server must actually be listening on loopback: a wildcard bind\n//     (\":16686\", \"0.0.0.0\", \"::\") or a loopback bind. Bound to one specific\n//     interface, say \"10.0.0.5:16686\", nothing answers on loopback.\n//   - TLS must be off. A server certificate carries a SAN for the name operators","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/cmd/jaeger/internal/extension/jaegerquery/internal/flags.go#L150-L186","documentation":"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.","triggerScenarios":"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}].","commonSituations":"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.","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."],"exampleFix":"// before\nagent_headers:\n  - name: Authorization\n    value: \"Bearer x\"\n  - name: Authorization\n    value: \"Bearer y\"\n// after\nagent_headers:\n  - name: Authorization\n    value: \"Bearer x\"","handlingStrategy":"validation","validationCode":"names := map[string]bool{}\nfor _, h := range cfg.AgentHeaders {\n    if names[h.Name] {\n        return fmt.Errorf(\"duplicate agent header: %s\", h.Name)\n    }\n    names[h.Name] = true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["config","validation","startup"],"backgroundTag":"duplicate-config-key","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}