router-for-me/CLIProxyAPI · error
plugin store resolved auth header value is empty
Error message
plugin store resolved auth header value is empty
What it means
Thrown while applying a header-type plugin-store auth rule: the header value resolved to an empty byte slice. internal/pluginstore/auth.go checks len(item.HeaderValue) == 0 before calling headers.Set, because sending a named header with an empty value would produce a guaranteed-401 request. The value usually comes from an environment variable (header-value-env), so an unset or blank env var is the typical root cause.
Source
Thrown at internal/pluginstore/auth.go:301
case AuthTypeBasic:
if len(item.Username) == 0 || len(item.Password) == 0 {
return false, fmt.Errorf("plugin store resolved basic auth is incomplete")
}
credential := make([]byte, 0, len(item.Username)+1+len(item.Password))
credential = append(credential, item.Username...)
credential = append(credential, ':')
credential = append(credential, item.Password...)
encoded := base64.StdEncoding.EncodeToString(credential)
for index := range credential {
credential[index] = 0
}
headers.Set("Authorization", "Basic "+encoded)
case AuthTypeHeader:
if strings.TrimSpace(item.HeaderName) == "" {
return false, fmt.Errorf("plugin store resolved auth missing header-name")
}
if len(item.HeaderValue) == 0 {
return false, fmt.Errorf("plugin store resolved auth header value is empty")
}
headers.Set(item.HeaderName, string(item.HeaderValue))
default:
return false, fmt.Errorf("unsupported plugin store resolved auth type %q", item.Type)
}
return true, nil
}
func validatePluginStoreRequestURL(auth []AuthConfig, requestURL string, kind string) error {
parsed, errParse := url.Parse(strings.TrimSpace(requestURL))
if errParse != nil || parsed.Scheme == "" || parsed.Host == "" {
return fmt.Errorf("invalid plugin store url")
}
if parsed.User != nil {
return fmt.Errorf("plugin store url must not contain credentials")
}
if hasSensitiveQueryParameter(parsed) {
return fmt.Errorf("plugin store url contains sensitive query parameter")View on GitHub (pinned to 78f0c4079e)
Solutions
- Set the referenced env var to the real token value in the environment that runs the server (export it, add it to .env, or the systemd/docker env)
- Confirm the header-value-env name in config.yaml matches the variable name exactly (case-sensitive)
- Check for whitespace-only values — the resolver trims and yields an empty Secret
- Restart the process so the env change is picked up
Example fix
# before (.env) # PLUGIN_API_KEY= (empty) # after (.env) PLUGIN_API_KEY=actual-secret-value
Defensive patterns
Strategy: validation
Validate before calling
if strings.EqualFold(strings.TrimSpace(rule.Type), "header") {
v := strings.TrimSpace(os.Getenv(rule.HeaderValueEnv))
if v == "" {
return fmt.Errorf("env %s unset; will fail auth resolution", rule.HeaderValueEnv)
}
} Prevention
- Fail fast at boot: resolve every configured *-env secret during startup and abort if any is empty
- Run CLIProxyAPI under a process manager that fails when required env vars are missing (systemd EnvironmentFile with strict mode, docker --env-file plus a preflight)
When it happens
Trigger: A header-type auth rule matches the request URL and kind, but the env var named by header-value-env is unset, empty, or whitespace that was trimmed to zero bytes during resolution.
Common situations: Env var not exported in the shell/service unit that runs CLIProxyAPI; .env file missing the key; secret rotated to an empty value; deploy environment (container/systemd) differs from the developer shell where the variable exists.
Related errors
- plugin store auth missing %s
- plugin store auth missing header-name
- unsupported plugin store auth type %q
- plugin store resolved auth token is empty
- plugin store resolved basic auth is incomplete
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/cbed9e2715fb131e.
Report an issue: GitHub.