router-for-me/CLIProxyAPI · error
plugin host is unavailable
Error message
plugin host is unavailable
What it means
executorAdapterForPlugin returns this when the receiver Host itself is nil. It is a programming/lifecycle error: caller invoked CountPluginExecutor/ExecutePluginExecutor-style routing on a nil *Host, typically because the plugin host was never initialized in this process or was already torn down and the pointer zeroed.
Source
Thrown at internal/pluginhost/executor_route.go:114
adapter, errAdapter := h.executorAdapterForPlugin(pluginID)
if errAdapter != nil {
return nil, errAdapter
}
return adapter.ExecuteStream(ctx, (*coreauth.Auth)(nil), req, opts)
}
// CountPluginExecutor executes a count-tokens request with the named plugin executor without changing the requested model.
func (h *Host) CountPluginExecutor(ctx context.Context, pluginID string, req coreexecutor.Request, opts coreexecutor.Options) (coreexecutor.Response, error) {
adapter, errAdapter := h.executorAdapterForPlugin(pluginID)
if errAdapter != nil {
return coreexecutor.Response{}, errAdapter
}
return adapter.CountTokens(ctx, (*coreauth.Auth)(nil), req, opts)
}
func (h *Host) executorAdapterForPlugin(pluginID string) (*executorAdapter, error) {
if h == nil {
return nil, fmt.Errorf("plugin host is unavailable")
}
pluginID = strings.TrimSpace(pluginID)
if pluginID == "" {
return nil, fmt.Errorf("target executor plugin id is required")
}
for _, record := range h.activeRecords() {
if record.id != pluginID {
continue
}
if h.isPluginFused(record.id) {
return nil, fmt.Errorf("plugin executor %s is unavailable", pluginID)
}
executor := record.plugin.Capabilities.Executor
if executor == nil {
return nil, fmt.Errorf("plugin %s does not declare an executor", pluginID)
}
provider, okProvider := h.executorProvider(record, executor)
if !okProvider {View on GitHub (pinned to 78f0c4079e)
Solutions
- Ensure the plugin host is created and attached to the service before any request can be routed to a plugin executor.
- Guard call sites: skip plugin-executor routing when the host is nil rather than calling into it.
- If using official cmd/server, report a bug — this state should not be reachable there.
Example fix
// before
adapter, err := host.executorAdapterForPlugin(pluginID) // host may be nil
// after
if host == nil {
return nil, fmt.Errorf("plugin routing requested but plugin host is not initialized")
}
adapter, err := host.executorAdapterForPlugin(pluginID) Defensive patterns
Strategy: type-guard
Validate before calling
if host == nil {
return fmt.Errorf("plugin executor routing skipped: plugin host not initialized")
} Type guard
func pluginHostReady(h *pluginhost.Host) bool {
return h != nil
} Try / catch
// Go: defend with a nil-receiver check rather than catch
if h == nil {
return coreexecutor.Response{}, fmt.Errorf("plugin host unavailable")
}
resp, err := h.CountPluginExecutor(ctx, pluginID, req, opts) Prevention
- Make plugin host initialization mandatory before wiring executor routes.
- Fail service startup if plugin-dependent routes exist but the host is nil.
When it happens
Trigger: Calling Host.CountPluginExecutor (or the execute route that uses executorAdapterForPlugin) on a nil host pointer: embedding code that skips plugin host setup but still routes model requests to plugin executors, or a code path that reads the host from an optional field that was never set.
Common situations: Custom embeddings that treat the plugin host as optional; races during shutdown where the host reference is cleared while a request is being routed; tests constructing partial service objects.
Related errors
- host model executor is unavailable
- Codex Alpha Search API key base URL unavailable
- plugin client is closed
- target executor plugin id is required
- plugin executor %s is unavailable
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/3372674acdae1f96.
Report an issue: GitHub.