router-for-me/CLIProxyAPI · error
auth provider poll login panic: %v
Error message
auth provider poll login panic: %v
What it means
This error is raised by the panic guard around a plugin's AuthProvider.PollLogin capability. If a plugin's poll-stage login handler panics while completing an OAuth-style flow, the host recovers it, fuses the plugin, and returns this error instead of crashing the process. The panic originated in plugin code, and the poll is treated as unhandled.
Source
Thrown at internal/pluginhost/auth_provider.go:314
}
var pollMetadata map[string]any
if len(metadata) > 0 {
pollMetadata = metadata[0]
}
return h.callPollLogin(ctx, *record, provider, state, pollMetadata)
}
func (h *Host) callPollLogin(ctx context.Context, record capabilityRecord, provider, state string, metadata map[string]any) (resp pluginapi.AuthLoginPollResponse, handled bool, err error) {
authProvider := record.plugin.Capabilities.AuthProvider
if h == nil || authProvider == nil || h.isPluginFused(record.id) || !h.recordCurrent(record) {
return pluginapi.AuthLoginPollResponse{}, false, nil
}
defer func() {
if recovered := recover(); recovered != nil {
h.fusePlugin(record.id, "AuthProvider.PollLogin", recovered)
resp = pluginapi.AuthLoginPollResponse{}
handled = false
err = fmt.Errorf("auth provider poll login panic: %v", recovered)
}
}()
req := pluginapi.AuthLoginPollRequest{
Provider: normalizeProviderID(provider),
State: strings.TrimSpace(state),
Host: h.hostConfigSummary(),
HTTPClient: h.newHTTPClient(nil),
Metadata: cloneAnyMap(metadata),
}
resp, errPoll := authProvider.PollLogin(ctx, req)
if errPoll != nil {
return pluginapi.AuthLoginPollResponse{}, true, errPoll
}
return resp, true, nil
}
func (h *Host) RefreshAuth(ctx context.Context, auth *coreauth.Auth) (refreshed *coreauth.Auth, handled bool, err error) {
if h == nil || auth == nil {View on GitHub (pinned to 78f0c4079e)
Solutions
- Inspect the fusePlugin log entry for 'AuthProvider.PollLogin' and the recovered value to pinpoint the panicking plugin.
- Verify the state and metadata you pass to the poll endpoint are exactly what the plugin's StartLogin returned (do not re-serialize or trim them yourself).
- Run the plugin's PollLogin standalone with the same State/Metadata to capture the full stack trace.
- Fix or update the plugin so PollLogin validates inputs and returns errors; add nil checks for Metadata map access.
- Restart the host to clear the fuse after fixing the plugin.
Example fix
// plugin side, before
func (p *Provider) PollLogin(ctx context.Context, req pluginapi.AuthLoginPollRequest) (pluginapi.AuthLoginPollResponse, error) {
parts := strings.Split(req.State, ":")
return pluginapi.AuthLoginPollResponse{Token: parts[1]}, nil // panics: index out of range
}
// after
func (p *Provider) PollLogin(ctx context.Context, req pluginapi.AuthLoginPollRequest) (pluginapi.AuthLoginPollResponse, error) {
parts := strings.Split(req.State, ":")
if len(parts) != 2 {
return pluginapi.AuthLoginPollResponse{}, fmt.Errorf("poll login: malformed state")
}
return pluginapi.AuthLoginPollResponse{Token: parts[1]}, nil
} Defensive patterns
Strategy: try-catch
Validate before calling
if strings.TrimSpace(state) == "" {
return fmt.Errorf("poll login requires the state returned by start login")
} Type guard
func validPollInput(state string, metadata map[string]any) bool {
return strings.TrimSpace(state) != "" && metadata != nil
} Try / catch
resp, handled, err := host.CallPollLogin(ctx, provider, state, metadata)
if err != nil {
if strings.Contains(err.Error(), "poll login panic") {
log.WithField("provider", provider).WithError(err).Error("plugin crashed during poll; user must restart login")
}
return err
}
if !handled {
// plugin gone (fused/removed): restart the login flow from start
} Prevention
- Pass the start-login response's state/metadata through verbatim; do not trim or re-encode them yourself.
- Persist the start-login state so a poll retry after plugin failure can restart cleanly.
- Test the full start+poll cycle after every plugin upgrade.
When it happens
Trigger: Polling login completion for a plugin-backed provider (state + metadata passed from the start-login response) when the plugin's PollLogin panics: nil State string assumptions, malformed state parsing, type assertions on Metadata values, or nil HTTPClient usage.
Common situations: A plugin that expects the state token in a specific format but receives a trimmed/empty state (host applies strings.TrimSpace before passing); plugin written for a different poll response schema; partially completed login where metadata from StartLogin was lost.
Related errors
- auth provider start login panic: %v
- auth provider panic: %v
- auth provider refresh panic: %v
- plugin executor %s refresh panic: %v
- auth provider %s returned auth without provider
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/93870fad77e88c3b.
Report an issue: GitHub.