{"record":{"id":"5f03bc13fda4f9aa","repo":"router-for-me/CLIProxyAPI","slug":"auth-provider-panic-v","errorCode":null,"errorMessage":"auth provider panic: %v","messagePattern":"auth provider panic: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/auth_provider.go","lineNumber":212,"sourceCode":"func (h *Host) callParseAuth(ctx context.Context, record capabilityRecord, req pluginapi.AuthParseRequest) (auth *coreauth.Auth, handled bool, err error) {\n\tauths, handled, errParseAuths := h.callParseAuths(ctx, record, req)\n\tif errParseAuths != nil || !handled || len(auths) == 0 {\n\t\treturn nil, handled, errParseAuths\n\t}\n\treturn auths[0], true, nil\n}\n\nfunc (h *Host) callParseAuths(ctx context.Context, record capabilityRecord, req pluginapi.AuthParseRequest) (auths []*coreauth.Auth, handled bool, err error) {\n\tprovider := record.plugin.Capabilities.AuthProvider\n\tif h == nil || provider == nil || h.isPluginFused(record.id) || !h.recordCurrent(record) {\n\t\treturn nil, false, nil\n\t}\n\tdefer func() {\n\t\tif recovered := recover(); recovered != nil {\n\t\t\th.fusePlugin(record.id, \"AuthProvider.ParseAuth\", recovered)\n\t\t\tauths = nil\n\t\t\thandled = false\n\t\t\terr = fmt.Errorf(\"auth provider panic: %v\", recovered)\n\t\t}\n\t}()\n\tif req.Host.AuthDir == \"\" {\n\t\treq.Host = h.hostConfigSummary()\n\t}\n\treq.Provider = normalizeProviderID(req.Provider)\n\tif req.Provider == \"\" {\n\t\treq.Provider = normalizeProviderID(provider.Identifier())\n\t}\n\treq.RawJSON = bytes.Clone(req.RawJSON)\n\tresp, errParse := provider.ParseAuth(ctx, req)\n\tif errParse != nil {\n\t\treturn nil, false, errParse\n\t}\n\tif !resp.Handled {\n\t\treturn nil, false, nil\n\t}\n\tdatas := pluginAuthParseResponseAuths(resp)","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/auth_provider.go#L194-L230","documentation":"Constructed in Host.callParseAuths' recover() handler when the plugin's AuthProvider.ParseAuth implementation panics. The host trips the plugin's fuse (fusePlugin) so the misbehaving plugin is skipped in subsequent calls, and returns this error describing the recovered panic value.","triggerScenarios":"A plugin's ParseAuth hits a nil dereference, index-out-of-range, or assertion panic while parsing auth data; once fused, the plugin stops being consulted until fuse conditions clear.","commonSituations":"Third-party plugin bug triggered by unexpected auth payload shapes; plugin built against an older contract passing unexpected types; empty/edge-case RawJSON reaching a plugin that assumes fields exist.","solutions":["Check host logs for the fuse record identifying the plugin id and panic stack","Update or patch the plugin so ParseAuth handles the input defensively and returns errors instead of panicking","After fixing, restart or un-fuse the plugin per the host's fuse policy so it is consulted again","As a workaround, remove/disable the faulty plugin so other providers continue working"],"exampleFix":"// before (plugin side)\nfunc (p *Provider) ParseAuth(ctx context.Context, req AuthParseRequest) (*AuthParseResponse, error) {\n    return &AuthParseResponse{Auth: AuthData{Provider: req.RawJSON[\"type\"]}}, nil // may panic\n}\n\n// after\nfunc (p *Provider) ParseAuth(ctx context.Context, req AuthParseRequest) (*AuthParseResponse, error) {\n    t, _ := req.RawJSON[\"type\"].(string)\n    if t == \"\" {\n        return nil, fmt.Errorf(\"auth payload missing type\")\n    }\n    return &AuthParseResponse{Auth: AuthData{Provider: t}}, nil\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"auth provider panic\") {\n    // identify plugin from the message/logs; it is now fused — disable or update it,\n    // and let other providers serve the request\n}","preventionTips":["Plugin authors: never let ParseAuth panic; validate inputs and return errors","Wrap risky plugin code in defensive checks for nil maps/slices before indexing","Monitor fuse events in logs to catch faulty plugins early"],"tags":["go","pluginhost","auth","plugin","panic","circuit-breaker"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}