{"record":{"id":"6be8f80b13c76a18","repo":"router-for-me/CLIProxyAPI","slug":"plugin-store-auth-missing-header-name","errorCode":null,"errorMessage":"plugin store auth missing header-name","messagePattern":"plugin store auth missing header-name","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"internal/pluginstore/auth.go","lineNumber":255,"sourceCode":"\t\ttoken, errToken := envValueRequired(item.TokenEnv, \"token-env\")\n\t\tif errToken != nil {\n\t\t\treturn false, errToken\n\t\t}\n\t\theaders.Set(\"Authorization\", \"Bearer \"+token)\n\tcase AuthTypeBasic:\n\t\tusername, errUsername := envValueRequired(item.UsernameEnv, \"username-env\")\n\t\tif errUsername != nil {\n\t\t\treturn false, errUsername\n\t\t}\n\t\tpassword, errPassword := envValueRequired(item.PasswordEnv, \"password-env\")\n\t\tif errPassword != nil {\n\t\t\treturn false, errPassword\n\t\t}\n\t\tencoded := base64.StdEncoding.EncodeToString([]byte(username + \":\" + password))\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 auth missing header-name\")\n\t\t}\n\t\tvalue, errValue := envValueRequired(item.HeaderValueEnv, \"header-value-env\")\n\t\tif errValue != nil {\n\t\t\treturn false, errValue\n\t\t}\n\t\theaders.Set(item.HeaderName, value)\n\tcase AuthTypeGitHubToken:\n\t\ttoken, errToken := envValueRequired(item.TokenEnv, \"token-env\")\n\t\tif errToken != nil {\n\t\t\treturn false, errToken\n\t\t}\n\t\theaders.Set(\"Authorization\", \"Bearer \"+token)\n\tdefault:\n\t\treturn false, fmt.Errorf(\"unsupported plugin store auth type %q\", item.Type)\n\t}\n\treturn true, nil\n}\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/auth.go#L237-L273","documentation":"When a plugin store's auth config declares type \"header\", the config must also provide header-name; the env-based auth applier rejects the config otherwise. The env var supplying the header value (header-value-env) is only read after this check, so the error is purely a config-completeness failure.","triggerScenarios":"A plugin store entry in config.yaml with auth.type: header but missing or blank auth.header-name.","commonSituations":"Hand-edited YAML where the header-name key was typo'd (e.g. headerName) or omitted; migrating a bearer-auth store to header auth and forgetting the new field.","solutions":["Add header-name to the store's auth block in the plugin store config","Validate the store config with a schema/lint step before deploying","Check for YAML indentation errors that silently detach header-name from the auth map"],"exampleFix":"# before\nauth:\n  type: header\n  header-value-env: MY_HEADER\n\n# after\nauth:\n  type: header\n  header-name: X-Custom-Token\n  header-value-env: MY_HEADER","handlingStrategy":"validation","validationCode":"func validateStoreAuth(item StoreAuthConfig) error {\n    switch strings.ToLower(strings.TrimSpace(item.Type)) {\n    case \"\", \"none\":\n        return nil\n    case \"header\":\n        if strings.TrimSpace(item.HeaderName) == \"\" {\n            return fmt.Errorf(\"auth.type 'header' requires auth.header-name\")\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint plugin store config in CI before deploy","Copy auth blocks from config.example.yaml to get field names right"],"tags":["config","plugin-store","auth","validation"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}