router-for-me/CLIProxyAPI · error

plugin store resolved auth token is empty

Error message

plugin store resolved auth token is empty

What it means

The resolved-auth applier (used when auth secrets have already been materialized into ResolvedAuthConfig, e.g. from the management API or a secret store) rejects bearer/github-token auth when the resolved Token field is empty. Unlike the env-based path, nothing is read from the environment here — the token must already be present in the resolved struct.

Source

Thrown at internal/pluginstore/auth.go:280

	case AuthTypeGitHubToken:
		token, errToken := envValueRequired(item.TokenEnv, "token-env")
		if errToken != nil {
			return false, errToken
		}
		headers.Set("Authorization", "Bearer "+token)
	default:
		return false, fmt.Errorf("unsupported plugin store auth type %q", item.Type)
	}
	return true, nil
}

func applyResolvedPluginStoreAuth(headers http.Header, item ResolvedAuthConfig) (bool, error) {
	switch strings.ToLower(strings.TrimSpace(item.Type)) {
	case "", AuthTypeNone:
		return false, nil
	case AuthTypeBearer, AuthTypeGitHubToken:
		if len(item.Token) == 0 {
			return false, fmt.Errorf("plugin store resolved auth token is empty")
		}
		headers.Set("Authorization", "Bearer "+string(item.Token))
	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")

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Supply a non-empty token in the resolved auth (re-submit via the management API or fix the source config)
  2. Verify the secret/token reference actually resolves: check the secret key name and that the env var or secret store value exists
  3. If the token is intentionally absent, set auth type to none instead of bearer

Example fix

# before
PUT /management/plugin-store
{"auth": {"type": "bearer"}}

# after
PUT /management/plugin-store
{"auth": {"type": "bearer", "token": "<resolved-token-value>"}}
Defensive patterns

Strategy: validation

Validate before calling

func validateResolvedAuth(item ResolvedAuthConfig) error {
    switch strings.ToLower(strings.TrimSpace(item.Type)) {
    case "bearer", "github-token":
        if len(item.Token) == 0 {
            return fmt.Errorf("auth type %q requires a resolved token", item.Type)
        }
    }
    return nil
}

Prevention

When it happens

Trigger: A resolved store auth of type bearer or github-token whose token resolved to empty: the referenced secret was missing, the secret key name wrong, or the management operation submitted an auth object without a token.

Common situations: Management API requests updating plugin store auth without the token field; secret store entry deleted or renamed after the store was configured; env var referenced by the resolver unset at resolution time.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/91bb44f3efcfcc99. Report an issue: GitHub.