{"record":{"id":"cc286f11c44d5ab4","repo":"m1k1o/neko","slug":"plugin-s-failed-to-start-w","errorCode":null,"errorMessage":"plugin '%s' failed to start: %w","messagePattern":"plugin '(.+?)' failed to start: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/plugins/dependency.go","lineNumber":52,"sourceCode":"\treturn nil, false\n}\n\nfunc (a *dependency) startPlugin(pm types.PluginManagers) error {\n\tif a.invoked {\n\t\treturn nil\n\t}\n\n\ta.invoked = true\n\n\tfor _, do := range a.dependsOn {\n\t\tif err := do.startPlugin(pm); err != nil {\n\t\t\treturn fmt.Errorf(\"plugin's '%s' dependency: %w\", a.plugin.Name(), err)\n\t\t}\n\t}\n\n\terr := a.plugin.Start(pm)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"plugin '%s' failed to start: %w\", a.plugin.Name(), err)\n\t}\n\n\ta.logger.Info().Str(\"plugin\", a.plugin.Name()).Msg(\"plugin started\")\n\treturn nil\n}\n\ntype dependiencies struct {\n\tdeps   map[string]*dependency\n\tlogger zerolog.Logger\n}\n\nfunc (d *dependiencies) addPlugin(plugin types.Plugin) error {\n\tpluginName := plugin.Name()\n\n\tplug, ok := d.deps[pluginName]\n\tif !ok {\n\t\tplug = &dependency{}\n\t} else if plug.plugin != nil {","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/m1k1o/neko/blob/b0f01cedea68893e85a3fd852c0521238c285695/server/internal/plugins/dependency.go#L34-L70","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Look at the wrapped inner error for the concrete failure reason from the plugin's Start","Fix the plugin's configuration values referenced by the inner error","Ensure any external service/hardware the plugin needs is reachable before startup","Update the plugin to a version compatible with the current backend/config schema"],"exampleFix":"// before (config)\nplugins: {\"filetransfer\": {\"enabled\": true, \"path\": \"/nonexistent\"}}\n// after\nplugins: {\"filetransfer\": {\"enabled\": true, \"path\": \"/srv/uploads\"}}","handlingStrategy":"try-catch","validationCode":"if cfg, ok := pm.Config(plugin.Name()); !ok || !cfg.Valid() {\n\treturn fmt.Errorf(\"plugin %s has missing/invalid config; fix before starting\", plugin.Name())\n}","typeGuard":"func isPluginStartError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to start\")\n}","tryCatchPattern":"if err := pm.Start(name); err != nil {\n\tif isPluginStartError(err) {\n\t\tlog.Printf(\"plugin %s unavailable, continuing degraded: %v\", name, err)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Validate plugin configuration against the plugin's schema before server start","Check external dependencies (ports, devices, services) the plugin needs are available","After upgrades, read the wrapped inner error for config keys that changed","Start plugins in dry-run/validate mode in CI to catch startup errors before deploy"],"tags":["plugins","startup","initialization"],"backgroundTag":"plugin-start-failed","analyzedSha":"b0f01cedea68893e85a3fd852c0521238c285695","analyzedAt":"2026-09-01T10:35:56.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}