{"record":{"id":"bec5ceba7a1be246","repo":"router-for-me/CLIProxyAPI","slug":"plugin-executor-s-has-no-provider-identifier","errorCode":null,"errorMessage":"plugin executor %s has no provider identifier","messagePattern":"plugin executor (.+?) has no provider identifier","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/executor_route.go","lineNumber":133,"sourceCode":"\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":115,"sourceCodeEnd":140,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/executor_route.go#L115-L140","documentation":"The plugin declares an Executor capability, but h.executorProvider cannot derive a provider identifier for it (okProvider == false). Without a provider identifier the host cannot register the executor into its provider registry, so routing fails with this error.","triggerScenarios":"An executor capability whose metadata omits or leaves blank the provider identifier field the host reads (e.g. Provider()/provider metadata method returning \"\"). The plugin structurally looks like an executor but is not identifiable.","commonSituations":"Plugin built against a newer or older pluginapi where the provider identifier accessor changed; a plugin that implements the Executor interface partially, leaving the identifier method's zero value; manifest field renamed between versions.","solutions":["Check the plugin's executor implementation: the provider identifier (as expected by the host's executorProvider) must return a non-empty value.","Rebuild the plugin against the same pluginapi version as the host.","If a third-party plugin, report to its maintainer that the executor capability lacks a provider identifier."],"exampleFix":"// plugin side, before\nfunc (e *Executor) Provider() string { return \"\" }\n\n// after\nfunc (e *Executor) Provider() string { return \"my-provider\" }","handlingStrategy":"validation","validationCode":"// Plugin-side self-check before returning the capability\nif strings.TrimSpace(myProviderID) == \"\" {\n    panic(\"executor capability configured without provider identifier\") // fail at plugin load, not per request\n}","typeGuard":"func executorHasProvider(h *pluginhost.Host, rec pluginRecord) bool {\n    _, ok := h.ExecutorProvider(rec, rec.Plugin.Capabilities.Executor)\n    return ok\n}","tryCatchPattern":"adapter, err := host.ExecutorAdapterForPlugin(pluginID)\nif err != nil && strings.Contains(err.Error(), \"no provider identifier\") {\n    // plugin defect: permanent; disable routing to it and file an issue\n    return disableRouteAndReport(pluginID, err)\n}","preventionTips":["Pin plugin builds to the host's pluginapi version.","Add a load-time contract test: every executor capability must expose a non-empty provider id."],"tags":["plugin","executor","capabilities","validation","pluginhost"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}