router-for-me/CLIProxyAPI · error
auth provider %s returned auth without provider
Error message
auth provider %s returned auth without provider
What it means
Thrown by Host.callParseAuths when a plugin's ParseAuth response contains an auth entry whose provider field cannot be normalized to a non-empty identifier, even after defaulting to the request provider and the plugin's own declared identifier. Every auth must be attributable to a provider, so the whole response is rejected.
Source
Thrown at internal/pluginhost/auth_provider.go:240
req.RawJSON = bytes.Clone(req.RawJSON)
resp, errParse := provider.ParseAuth(ctx, req)
if errParse != nil {
return nil, false, errParse
}
if !resp.Handled {
return nil, false, nil
}
datas := pluginAuthParseResponseAuths(resp)
auths = make([]*coreauth.Auth, 0, len(datas))
for _, data := range datas {
if strings.TrimSpace(data.Provider) == "" {
data.Provider = req.Provider
}
if strings.TrimSpace(data.Provider) == "" {
data.Provider = normalizeProviderID(provider.Identifier())
}
if normalizeProviderID(data.Provider) == "" {
return nil, true, fmt.Errorf("auth provider %s returned auth without provider", record.id)
}
parsed := h.AuthDataToCoreAuth(data, req.Path, req.FileName)
if parsed == nil {
return nil, true, fmt.Errorf("auth provider %s returned invalid auth data", record.id)
}
auths = append(auths, parsed)
}
return auths, true, nil
}
func pluginAuthParseResponseAuths(resp pluginapi.AuthParseResponse) []pluginapi.AuthData {
if len(resp.Auths) > 0 {
return append([]pluginapi.AuthData(nil), resp.Auths...)
}
return []pluginapi.AuthData{resp.Auth}
}
func (h *Host) StartLogin(ctx context.Context, provider string, baseURL string) (pluginapi.AuthLoginStartResponse, bool, error) {View on GitHub (pinned to 78f0c4079e)
Solutions
- In the plugin, always set Provider on each returned AuthData (or give the plugin a valid identifier)
- Pass a non-empty req.Provider when invoking parse so the default applies
- Upgrade the plugin to a version compatible with the current identifier normalization rules
Example fix
// before
resp.Auth = pluginapi.AuthData{} // provider empty
// after
resp.Auth = pluginapi.AuthData{Provider: "gemini"} Defensive patterns
Strategy: validation
Validate before calling
// plugin side, before returning:
for i := range resp.Auths {
if strings.TrimSpace(resp.Auths[i].Provider) == "" {
resp.Auths[i].Provider = myProviderID
}
} Try / catch
if err != nil && strings.Contains(err.Error(), "returned auth without provider") {
// plugin contract violation: fix the plugin's ParseAuth response
} Prevention
- Always populate Provider on returned AuthData in plugin implementations
- Set a valid plugin identifier so the host can default it
When it happens
Trigger: Plugin returns AuthData with empty/whitespace Provider while req.Provider and provider.Identifier() also normalize to empty (e.g. plugin identifier unset or non-normalizable); plugin returns auths array entries with provider omitted.
Common situations: Plugin author forgets to set Provider on returned AuthData and the plugin lacks a usable identifier; identifier format changed in a plugin version so normalizeProviderID yields empty.
Related errors
- auth provider %s returned invalid auth data
- invalid auth file name
- auth file name must end with .json
- json is required
- invalid auth json: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/6e216140016e7c55.
Report an issue: GitHub.