{"record":{"id":"b04c06adf2fef165","repo":"router-for-me/CLIProxyAPI","slug":"plugin-executor-s-is-unavailable-b04c06","errorCode":null,"errorMessage":"plugin executor %s is unavailable","messagePattern":"plugin executor (.+?) is unavailable","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/executor_route.go","lineNumber":125,"sourceCode":"\t\treturn coreexecutor.Response{}, errAdapter\n\t}\n\treturn adapter.CountTokens(ctx, (*coreauth.Auth)(nil), req, opts)\n}\n\nfunc (h *Host) executorAdapterForPlugin(pluginID string) (*executorAdapter, error) {\n\tif h == nil {\n\t\treturn nil, fmt.Errorf(\"plugin host is unavailable\")\n\t}\n\tpluginID = strings.TrimSpace(pluginID)\n\tif pluginID == \"\" {\n\t\treturn nil, fmt.Errorf(\"target executor plugin id is required\")\n\t}\n\tfor _, record := range h.activeRecords() {\n\t\tif record.id != pluginID {\n\t\t\tcontinue\n\t\t}\n\t\tif h.isPluginFused(record.id) {\n\t\t\treturn nil, fmt.Errorf(\"plugin executor %s is unavailable\", pluginID)\n\t\t}\n\t\texecutor := record.plugin.Capabilities.Executor\n\t\tif executor == nil {\n\t\t\treturn nil, fmt.Errorf(\"plugin %s does not declare an executor\", pluginID)\n\t\t}\n\t\tprovider, okProvider := h.executorProvider(record, executor)\n\t\tif !okProvider {\n\t\t\treturn nil, fmt.Errorf(\"plugin executor %s has no provider identifier\", pluginID)\n\t\t}\n\t\tregistration := newExecutorAdapterRegistration(h, record, provider, executor)\n\t\treturn registration.adapter, nil\n\t}\n\treturn nil, fmt.Errorf(\"plugin executor %s not found\", pluginID)\n}\n","sourceCodeStart":107,"sourceCodeEnd":140,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/executor_route.go#L107-L140","documentation":"The requested plugin record exists and is active, but isPluginFused reports it as fused — the host disabled it after repeated panics in its capability calls. All executor routing to it is refused with this error naming the plugin ID.","triggerScenarios":"Requesting execution/count-tokens on a plugin whose executor (or other capability) panicked enough times to trip the fuse; the fuse log entries (from fusePlugin) name the capability and recovered value that caused it.","commonSituations":"A buggy plugin build that panics under load; plugin incompatible with the current host API causing repeated panics; leftover fuse state after an earlier incident in a long-running process.","solutions":["Search logs for fusePlugin entries mentioning this plugin ID to find the originating panic and capability.","Fix or update the plugin (see the panic error's guidance), then restart/reload the host to clear the fuse.","If panics are load-triggered, capture the plugin's stack trace by running it standalone under the same inputs.","Consider removing the plugin from config until fixed so routing fails fast at config time rather than per-request."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"if host.IsPluginFused(pluginID) {\n    return fmt.Errorf(\"plugin %s is disabled after repeated panics; see fuse logs\", pluginID)\n}","typeGuard":"func executorUsable(h *pluginhost.Host, pluginID string) bool {\n    for _, rec := range h.ActiveRecords() {\n        if rec.ID == pluginID {\n            return !h.IsPluginFused(pluginID) && rec.Plugin.Capabilities.Executor != nil\n        }\n    }\n    return false\n}","tryCatchPattern":"resp, err := host.ExecutePluginExecutor(ctx, pluginID, req, opts)\nif err != nil && strings.Contains(err.Error(), \"is unavailable\") {\n    // fused plugin: permanent until restart; route to fallback provider/executor\n    return routeToFallback(model, req, opts)\n}","preventionTips":["Configure fallback executors/models so fused plugins degrade gracefully.","Monitor fuse events and auto-restart or alert when a plugin trips them.","Test plugins under load before deploying — fuses usually come from load-triggered panics."],"tags":["plugin","circuit-breaker","executor","panic","pluginhost"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}