{"record":{"id":"70ab7e684bc19966","repo":"gotify/server","slug":"plugin-instance-not-found","errorCode":null,"errorMessage":"plugin instance not found","messagePattern":"plugin instance not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"error","filePath":"api/plugin.go","lineNumber":137,"sourceCode":"//\t    schema:\n//\t        $ref: \"#/definitions/Error\"\n//\t  500:\n//\t    description: Internal Server Error\n//\t    schema:\n//\t        $ref: \"#/definitions/Error\"\nfunc (c *PluginAPI) EnablePlugin(ctx *gin.Context) {\n\twithID(ctx, \"id\", func(id uint) {\n\t\tconf, err := c.DB.GetPluginConfByID(id)\n\t\tif success := successOrAbort(ctx, 500, err); !success {\n\t\t\treturn\n\t\t}\n\t\tif conf == nil || !isPluginOwner(ctx, conf) {\n\t\t\tctx.AbortWithError(404, errors.New(\"unknown plugin\"))\n\t\t\treturn\n\t\t}\n\t\t_, err = c.Manager.Instance(id)\n\t\tif err != nil {\n\t\t\tctx.AbortWithError(404, errors.New(\"plugin instance not found\"))\n\t\t\treturn\n\t\t}\n\t\tif err := c.Manager.SetPluginEnabled(id, true); err == plugin.ErrAlreadyEnabledOrDisabled {\n\t\t\tctx.AbortWithError(400, err)\n\t\t} else if err != nil {\n\t\t\tctx.AbortWithError(500, err)\n\t\t}\n\t})\n}\n\n// DisablePlugin disables a plugin.\n// swagger:operation POST /plugin/{id}/disable plugin disablePlugin\n//\n// Disable a plugin.\n//\n//\t---\n//\tconsumes: [application/json]\n//\tproduces: [application/json]","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/api/plugin.go#L119-L155","documentation":"This 404 is returned by the plugin-enable endpoint after the plugin configuration was already verified to exist and be owned by the caller. It means Manager.Instance(id) failed to return a running plugin instance — i.e. the plugin binary/instance is not currently instantiated in the plugin manager, so it cannot be enabled. It is distinct from 'unknown plugin', which fires when the DB config is missing or the caller is not the owner.","triggerScenarios":"PATCH/POST to the enable-plugin endpoint with a valid, owned plugin ID whose instance cannot be resolved by Manager.Instance(id) (plugin process not running, not yet instantiated, or crashed).","commonSituations":"Plugin was deleted from the runtime but its DB config row still exists; plugin failed to start after a version upgrade; manager restarted and the plugin was not re-instantiated; stale UI cache pointing at a plugin whose instance was torn down.","solutions":["Verify the plugin instance is running: list instances from the manager and confirm the ID exists before enabling","Re-instantiate or restart the plugin (e.g. via the plugin install/start flow) so Manager.Instance(id) succeeds","Check manager logs for instantiation/startup failure for this plugin ID","If the DB config is stale, delete the plugin config and re-create it"],"exampleFix":"// before\n_, err = c.Manager.Instance(id)\nif err != nil {\n    ctx.AbortWithError(404, errors.New(\"plugin instance not found\"))\n    return\n}\n// after\n_, err = c.Manager.Instance(id)\nif err != nil {\n    if errors.Is(err, plugin.ErrNotRunning) {\n        ctx.AbortWithError(409, errors.New(\"plugin is configured but not running; start it first\"))\n    } else {\n        ctx.AbortWithError(404, errors.New(\"plugin instance not found\"))\n    }\n    return\n}","handlingStrategy":"validation","validationCode":"resp, err := client.Get(baseURL + \"/api/plugins\")\nif err != nil { return err }\nvar plugins []Plugin\njson.NewDecoder(resp.Body).Decode(&plugins)\nfor _, p := range plugins {\n    if p.ID == targetID { /* instance should be resolvable */ return nil }\n}\nreturn fmt.Errorf(\"plugin %d not running; cannot enable\", targetID)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["List running plugin instances before enable/disable calls","After manager restarts, re-check instance availability before mutating plugin state","Alert on plugin crash events so state is known before API calls","Delete orphaned plugin configs whose instances no longer exist"],"tags":["http-404","plugin-manager","gin"],"backgroundTag":"plugin-instance-not-found","analyzedSha":"14bfc256276775c425f988d621dccfe705de18ac","analyzedAt":"2026-09-05T12:52:36.781Z","contentChangedAt":"2026-09-05T12:52:36.781Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}