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

  1. In the plugin, always set Provider on each returned AuthData (or give the plugin a valid identifier)
  2. Pass a non-empty req.Provider when invoking parse so the default applies
  3. 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

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


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