router-for-me/CLIProxyAPI · error

plugin does not declare an executor

Error message

plugin %s does not declare an executor

What it means

The plugin with the given ID is active but its manifest/capability set has no Executor capability (record.plugin.Capabilities.Executor == nil). The host was asked to build an executor adapter for a plugin that simply does not provide model execution.

Solutions

  1. Verify the plugin's manifest declares an executor capability and that its id matches the routing config exactly.
  2. Correct the model-to-plugin mapping in config to point at the plugin that actually provides the executor.
  3. Update/reinstall the plugin to a version that declares Executor.

Example fix

# before (config.yaml)
models:
  - name: "my-model"
    plugin: "my-auth-plugin"     # no executor capability

# after
models:
  - name: "my-model"
    plugin: "my-executor-plugin" # declares Executor
Defensive patterns

Strategy: validation

Validate before calling

for _, rec := range host.ActiveRecords() {
    if rec.ID == wantedPluginID && rec.Plugin.Capabilities.Executor != nil {
        return nil // routing target is valid
    }
}
return fmt.Errorf("plugin %s has no executor capability", wantedPluginID)

Type guard

func pluginDeclaresExecutor(rec pluginRecord) bool {
    return rec.Plugin.Capabilities.Executor != nil
}

Try / catch

adapter, err := host.ExecutorAdapterForPlugin(pluginID)
if err != nil && strings.Contains(err.Error(), "does not declare an executor") {
    return configErrorf("model %s routed to non-executor plugin %s; fix models config", model, pluginID)
}

Prevention

When it happens

Trigger: Routing execution to a plugin that only provides auth, command-line, or router capabilities; typo in the plugin id in model routing config that happens to match a non-executor plugin; plugin version that dropped or renamed the executor capability.

Common situations: Config lists the wrong plugin id for a model; plugin downgrade where executor support was removed; a manifest parsing issue silently dropping the Executor capability.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/3e2b689da2c82427. Report an issue: GitHub.

Appendix: source

Thrown at internal/pluginhost/executor_route.go:129

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 {
			return nil, fmt.Errorf("plugin executor %s has no provider identifier", pluginID)
		}
		registration := newExecutorAdapterRegistration(h, record, provider, executor)
		return registration.adapter, nil
	}
	return nil, fmt.Errorf("plugin executor %s not found", pluginID)
}

View on GitHub (pinned to 78f0c4079e)