router-for-me/CLIProxyAPI · error
resource handler panic: %v
Error message
resource handler panic: %v
What it means
Identical recovery wrapper for plugin resource routes (mounted under the resource plugin base path): a panicking HandleManagement in a resource handler is caught, the plugin is fused, and this error is returned. Keeps panics in resource endpoints from crashing the host process.
Source
Thrown at internal/pluginhost/management.go:359
}
func escapeManagementResponseBody(resp pluginapi.ManagementResponse) []byte {
body, okEscaped := htmlsanitize.JSONBodyIfLikely(resp.Body, resp.Headers.Get("Content-Type"))
if !okEscaped {
return resp.Body
}
return body
}
func (h *Host) callResourceHandler(ctx context.Context, record resourceRouteRecord, req pluginapi.ManagementRequest) (resp pluginapi.ManagementResponse, err error) {
if h == nil || record.route.Handler == nil || h.isPluginFused(record.pluginID) || !h.pluginIdentityCurrent(record.pluginID, record.path, record.version) {
return pluginapi.ManagementResponse{}, nil
}
defer func() {
if recovered := recover(); recovered != nil {
h.fusePlugin(record.pluginID, "ResourceHandler.HandleManagement", recovered)
resp = pluginapi.ManagementResponse{}
err = fmt.Errorf("resource handler panic: %v", recovered)
}
}()
return record.route.Handler.HandleManagement(ctx, req)
}
View on GitHub (pinned to 78f0c4079e)
Solutions
- Fix the panic in the plugin's resource handler; inspect the recovered value in the error message
- Add input validation and a top-level defer/recover inside the plugin handler to convert panics into 500 responses
- Disable the resource route or plugin until fixed, and restart the server to clear the fuse
Defensive patterns
Strategy: try-catch
Try / catch
resp, err := h.callResourceHandler(ctx, record, req)
if err != nil {
log.WithError(err).WithField("plugin", record.pluginID).Error("resource handler failed")
return http.StatusInternalServerError, []byte("plugin resource handler failed")
} Prevention
- Validate subpath parsing in resource handlers; guard slice/array indexing
- Add a top-level recover() in the plugin handler converting panics into 500 responses
- Note that after a fuse the plugin needs a reload/restart to serve again
When it happens
Trigger: A request to a plugin's resource endpoint (resourcePluginBasePath/<pluginID>/...) triggers a panic inside the plugin's resource handler.
Common situations: Resource handlers parsing user-supplied subpaths or bodies without validation; plugins sharing state with management handlers and racing on reload.
Related errors
- management handler panic: %v
- management registrar panic: %v
- plugin executor %s stream panic: %v
- plugin executor %s refresh panic: %v
- plugin executor %s count tokens panic: %v
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/4d2f2f9420d90865.
Report an issue: GitHub.