{"record":{"id":"2f6a5bf0b9372a2d","repo":"router-for-me/CLIProxyAPI","slug":"plugin-store-resolved-auth-missing-header-name","errorCode":null,"errorMessage":"plugin store resolved auth missing header-name","messagePattern":"plugin store resolved auth missing header-name","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"internal/pluginstore/auth.go","lineNumber":298,"sourceCode":"\t\t\treturn false, fmt.Errorf(\"plugin store resolved auth token is empty\")\n\t\t}\n\t\theaders.Set(\"Authorization\", \"Bearer \"+string(item.Token))\n\tcase AuthTypeBasic:\n\t\tif len(item.Username) == 0 || len(item.Password) == 0 {\n\t\t\treturn false, fmt.Errorf(\"plugin store resolved basic auth is incomplete\")\n\t\t}\n\t\tcredential := make([]byte, 0, len(item.Username)+1+len(item.Password))\n\t\tcredential = append(credential, item.Username...)\n\t\tcredential = append(credential, ':')\n\t\tcredential = append(credential, item.Password...)\n\t\tencoded := base64.StdEncoding.EncodeToString(credential)\n\t\tfor index := range credential {\n\t\t\tcredential[index] = 0\n\t\t}\n\t\theaders.Set(\"Authorization\", \"Basic \"+encoded)\n\tcase AuthTypeHeader:\n\t\tif strings.TrimSpace(item.HeaderName) == \"\" {\n\t\t\treturn false, fmt.Errorf(\"plugin store resolved auth missing header-name\")\n\t\t}\n\t\tif len(item.HeaderValue) == 0 {\n\t\t\treturn false, fmt.Errorf(\"plugin store resolved auth header value is empty\")\n\t\t}\n\t\theaders.Set(item.HeaderName, string(item.HeaderValue))\n\tdefault:\n\t\treturn false, fmt.Errorf(\"unsupported plugin store resolved auth type %q\", item.Type)\n\t}\n\treturn true, nil\n}\n\nfunc validatePluginStoreRequestURL(auth []AuthConfig, requestURL string, kind string) error {\n\tparsed, errParse := url.Parse(strings.TrimSpace(requestURL))\n\tif errParse != nil || parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn fmt.Errorf(\"invalid plugin store url\")\n\t}\n\tif parsed.User != nil {\n\t\treturn fmt.Errorf(\"plugin store url must not contain credentials\")","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/auth.go#L280-L316","documentation":"Thrown while materializing resolved plugin-store auth of type 'header': the header name is empty or only whitespace. The pluginstore package (internal/pluginstore/auth.go) requires that a header-type auth rule define both a header name and a value before it can set an Authorization-style header on an outgoing registry/metadata/artifact request. This is a configuration-completeness check, not a network failure.","triggerScenarios":"A plugin store auth entry in config.yaml has type: header but the header-name field (or HEADER_NAME in the resolved config) is missing, empty, or contains only spaces, and a request URL matching that rule is about to be authenticated.","commonSituations":"Author copies a bearer-auth example and switches type to header without adding header-name; YAML indentation puts header-name under the wrong mapping; a management API / snapshot omits the field; trailing whitespace typo like header-name: \"\".","solutions":["Set header-name to a valid HTTP header name (e.g. X-Api-Key) on the header-type auth rule in config.yaml","Verify YAML indentation so header-name is a sibling of type/match, not nested elsewhere","If configuring via management API or resolved auth configs, ensure HeaderName is non-empty before calling ResolvedAuthForRequest","Re-run the store operation and confirm the error is gone"],"exampleFix":"# before\nplugin-store:\n  auth:\n    - match: https://plugins.example.com\n      type: header\n      header-value-env: PLUGIN_API_KEY\n\n# after\nplugin-store:\n  auth:\n    - match: https://plugins.example.com\n      type: header\n      header-name: X-Api-Key\n      header-value-env: PLUGIN_API_KEY","handlingStrategy":"validation","validationCode":"func hasHeaderName(r ResolvedAuthConfig) bool {\n\treturn strings.EqualFold(strings.TrimSpace(r.Type), AuthTypeHeader) &&\n\t\tstrings.TrimSpace(r.HeaderName) != \"\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint plugin-store auth rules at startup: every type: header rule must set header-name","Keep a YAML schema/checklist per auth type (none/bearer/basic/header/github-token) and diff configs against it in CI"],"tags":["config","auth","plugin-store","validation"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}