{"record":{"id":"585b68582a8dcff2","repo":"alibaba/open-code-review","slug":"header-name-must-not-be-empty","errorCode":null,"errorMessage":"header name must not be empty","messagePattern":"header name must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/config_cmd.go","lineNumber":943,"sourceCode":"\t\tentry.Setup = value\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown MCP server field %q: supported fields are type, command, args, env, url, headers, tools, setup\", field)\n\t}\n\n\tcfg.MCPServers[name] = entry\n\treturn nil\n}\n\n// parseMCPHeaders parses a JSON object of header key-value pairs.\n// Example: {\"Authorization\": \"Bearer $TOKEN\", \"X-Custom\": \"value\"}\nfunc parseMCPHeaders(value string) (map[string]string, error) {\n\tvar m map[string]string\n\tif err := json.Unmarshal([]byte(value), &m); err != nil {\n\t\treturn nil, fmt.Errorf(\"expected JSON object: %w\", err)\n\t}\n\tfor k, v := range m {\n\t\tif k == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"header name must not be empty\")\n\t\t}\n\t\tif v == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"header value for %q must not be empty\", k)\n\t\t}\n\t}\n\treturn m, nil\n}\n\nfunc (c *Config) ensureTelemetry() {\n\tif c.Telemetry == nil {\n\t\tc.Telemetry = &TelemetryConfig{}\n\t}\n}\n","sourceCodeStart":925,"sourceCodeEnd":957,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/config_cmd.go#L925-L957","documentation":"parseMCPHeaders validates each parsed header pair and rejects a header with an empty name using \"header name must not be empty\". An empty key in the JSON object cannot be sent as an HTTP header, so it is refused during config entry rather than failing later at request time.","triggerScenarios":"A headers JSON object containing an empty-string key, e.g. '{\"\":\"value\"}' — typically from template interpolation that produced an empty variable name, or accidental deletion of a key in an editor.","commonSituations":"Unset environment variable interpolated into the key position (e.g. '{\"$HDR_NAME\":\"v\"}' with $HDR_NAME empty via naive shell expansion); copy-paste that dropped the key.","solutions":["Provide a non-empty key for every pair: '{\"Authorization\":\"Bearer t\"}'","Check shell expansions used to build the JSON — ensure the key variable is set","Edit the stored config entry directly if it was written programmatically"],"exampleFix":"// before\nocr config set mcp-servers.myserver.headers '{\"\": \"bearer-token\"}'\n// after\nocr config set mcp-servers.myserver.headers '{\"Authorization\": \"Bearer token\"}'","handlingStrategy":"validation","validationCode":"func keysNonEmpty(s string) bool {\n    var m map[string]string\n    if json.Unmarshal([]byte(s), &m) != nil { return false }\n    for k := range m { if k == \"\" { return false } }\n    return true\n}","typeGuard":"func hasEmptyKey(m map[string]string) bool { _, ok := m[\"\"]; return ok }","tryCatchPattern":"if err := setMCPServerValue(cfg, name, \"headers\", raw); err != nil {\n    if strings.Contains(err.Error(), \"header name must not be empty\") { /* fix the empty key */ }\n    return err\n}","preventionTips":["Never build header keys from possibly-empty env expansions","Validate with jq: `jq 'keys | all(length > 0)'`","Review generated JSON before passing it to the setter"],"tags":["config","validation","http-headers","mcp"],"backgroundTag":"empty-field-validation","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}