m1k1o/neko · error

plugin '%s' failed to start: %w

Error message

plugin '%s' failed to start: %w

What it means

After all dependencies start successfully, startPlugin calls a.plugin.Start(pm). If the plugin's own Start method returns an error, it is wrapped as fmt.Errorf("plugin '%s' failed to start: %w", a.plugin.Name(), err) so the log and call sites know which plugin failed and why (the %w preserves the original error).

Source

Thrown at server/internal/plugins/dependency.go:52

	return nil, false
}

func (a *dependency) startPlugin(pm types.PluginManagers) error {
	if a.invoked {
		return nil
	}

	a.invoked = true

	for _, do := range a.dependsOn {
		if err := do.startPlugin(pm); err != nil {
			return fmt.Errorf("plugin's '%s' dependency: %w", a.plugin.Name(), err)
		}
	}

	err := a.plugin.Start(pm)
	if err != nil {
		return fmt.Errorf("plugin '%s' failed to start: %w", a.plugin.Name(), err)
	}

	a.logger.Info().Str("plugin", a.plugin.Name()).Msg("plugin started")
	return nil
}

type dependiencies struct {
	deps   map[string]*dependency
	logger zerolog.Logger
}

func (d *dependiencies) addPlugin(plugin types.Plugin) error {
	pluginName := plugin.Name()

	plug, ok := d.deps[pluginName]
	if !ok {
		plug = &dependency{}
	} else if plug.plugin != nil {

View on GitHub (pinned to b0f01cedea)

Solutions

  1. Look at the wrapped inner error for the concrete failure reason from the plugin's Start
  2. Fix the plugin's configuration values referenced by the inner error
  3. Ensure any external service/hardware the plugin needs is reachable before startup
  4. Update the plugin to a version compatible with the current backend/config schema

Example fix

// before (config)
plugins: {"filetransfer": {"enabled": true, "path": "/nonexistent"}}
// after
plugins: {"filetransfer": {"enabled": true, "path": "/srv/uploads"}}
Defensive patterns

Strategy: try-catch

Validate before calling

if cfg, ok := pm.Config(plugin.Name()); !ok || !cfg.Valid() {
	return fmt.Errorf("plugin %s has missing/invalid config; fix before starting", plugin.Name())
}

Type guard

func isPluginStartError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "failed to start")
}

Try / catch

if err := pm.Start(name); err != nil {
	if isPluginStartError(err) {
		log.Printf("plugin %s unavailable, continuing degraded: %v", name, err)
		return nil
	}
	return err
}

Prevention

When it happens

Trigger: Any plugin whose Start(pm) implementation returns a non-nil error — e.g. invalid plugin configuration, failure to acquire a resource (port, device, file), or an unrecoverable initialization error inside the plugin.

Common situations: Misconfigured plugin settings in the backend config file; a plugin requiring hardware or an external service that is unavailable; version mismatch where a plugin expects config keys that changed after an upgrade.

Related errors


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