m1k1o/neko · error

plugin ' ' not found

Error message

plugin '%s' not found

What it means

Returned by Manager.LookupService when no registered plugin matches pluginName (findPlugin on the dependency registry fails). LookupService exposes an exposable plugin's service; the lookup is purely by the name returned by plugin.Name().

Solutions

  1. Verify the exact plugin name (the value of plugin.Name()) and fix the LookupService argument
  2. Check startup logs for plugin load errors — if the plugin failed to load it will not be in the registry
  3. Ensure plugins are loaded and InitConfigs/Start completed before LookupService is called
  4. Guard the call site: treat the error as expected for optional plugins and fall back gracefully

Example fix

// before
svc, err := manager.LookupService("file_tranfer") // typo

// after
svc, err := manager.LookupService("filetransfer")
if err != nil {
    log.Warn().Err(err).Str("plugin", name).Msg("plugin service unavailable")
    return
}
Defensive patterns

Strategy: fallback

Validate before calling

// ensure plugin load phase completed and name exists before lookup
if len(manager.Plugins()) == 0 {
    return fmt.Errorf("plugins not loaded yet")
}
if _, ok := manager.plugins.findPlugin(name); !ok {
    return fmt.Errorf("unknown plugin %q; known: %v", name, knownNames())
}

Try / catch

svc, err := manager.LookupService(name)
if err != nil {
    if strings.Contains(err.Error(), "not found") {
        // optional plugin: degrade gracefully
        return nil, nil
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling LookupService(name) where name was never registered — typo in the name, the plugin failed to load/start earlier, or the plugin was removed (e.g. its deps entry deleted by the cycle-break in addPlugin).

Common situations: Typo'd plugin name in handler wiring; a plugin whose load failed at startup (see errors 67/68) so it never entered the registry; requesting a service before plugin load/init completed.

Related errors


AI-assisted analysis of m1k1o/neko@b0f01cedea (2026-09-01). Data as JSON: /api/errors/2e817618aa360b02. Report an issue: GitHub.

Appendix: source

Thrown at server/internal/plugins/manager.go:151

		} else {
			manager.logger.Err(err).Msg("failed to start plugins, skipping...")
		}
	}
}

func (manager *ManagerCtx) Shutdown() error {
	_ = manager.plugins.forEach(func(d *dependency) error {
		err := d.plugin.Shutdown()
		manager.logger.Err(err).Str("plugin", d.plugin.Name()).Msg("plugin shutdown")
		return nil
	})
	return nil
}

func (manager *ManagerCtx) LookupService(pluginName string) (any, error) {
	plug, ok := manager.plugins.findPlugin(pluginName)
	if !ok {
		return nil, fmt.Errorf("plugin '%s' not found", pluginName)
	}

	expPlug, ok := plug.plugin.(types.ExposablePlugin)
	if !ok {
		return nil, fmt.Errorf("plugin '%s' is not exposable", pluginName)
	}

	return expPlug.ExposeService(), nil
}

func (manager *ManagerCtx) Metadata() []types.PluginMetadata {
	var plugins []types.PluginMetadata

	_ = manager.plugins.forEach(func(d *dependency) error {
		dependsOn := make([]string, 0)
		deps, isDependalbe := d.plugin.(types.DependablePlugin)
		if isDependalbe {
			dependsOn = deps.DependsOn()

View on GitHub (pinned to b0f01cedea)