{"record":{"id":"2b7e0079712cc4c2","repo":"router-for-me/CLIProxyAPI","slug":"plugin-manifest-failed","errorCode":"plugin_manifest_failed","errorMessage":"release tag is required","messagePattern":"release tag is required","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"internal/api/handlers/management/plugin_store.go","lineNumber":418,"sourceCode":"\t\terrs = append(errs, fmt.Errorf(\"%s: %w\", tag, errInstall))\n\t}\n\treturn pluginstore.InstallResult{}, fmt.Errorf(\"install release by tag: %w\", errors.Join(errs...))\n}\n\nfunc pluginStoreManifestForInstall(source pluginstore.Source, plugin pluginstore.Plugin, result pluginstore.InstallResult) (pluginstore.Manifest, error) {\n\tinstallType := strings.TrimSpace(result.InstallType)\n\tif installType == \"\" {\n\t\tinstallType = pluginstore.PluginInstallType(plugin)\n\t}\n\tswitch installType {\n\tcase pluginstore.InstallTypeDirect:\n\t\tplugin.Version = strings.TrimSpace(result.Version)\n\t\tplugin.Install = pluginstore.NormalizeInstallPlan(plugin.Install)\n\t\treturn pluginstore.ManifestFromPlugin(source, plugin)\n\tcase pluginstore.InstallTypeGitHubRelease:\n\t\treleaseTag := strings.TrimSpace(result.ReleaseTag)\n\t\tif releaseTag == \"\" {\n\t\t\treturn pluginstore.Manifest{}, fmt.Errorf(\"release tag is required\")\n\t\t}\n\t\treturn pluginstore.ManifestFromRelease(source, plugin, pluginstore.Release{TagName: releaseTag})\n\tdefault:\n\t\treturn pluginstore.Manifest{}, fmt.Errorf(\"unsupported install type %q\", result.InstallType)\n\t}\n}\n\nfunc pluginInstallRequestedVersion(c *gin.Context) (string, error) {\n\trequestedVersion := strings.TrimSpace(c.Query(\"version\"))\n\tif c == nil || c.Request == nil || c.Request.Body == nil || c.Request.Body == http.NoBody {\n\t\treturn requestedVersion, nil\n\t}\n\tbody, errRead := io.ReadAll(c.Request.Body)\n\tif errRead != nil {\n\t\treturn \"\", fmt.Errorf(\"read install request: %w\", errRead)\n\t}\n\tif strings.TrimSpace(string(body)) == \"\" {\n\t\treturn requestedVersion, nil","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/api/handlers/management/plugin_store.go#L400-L436","documentation":"Returned by pluginStoreManifestForInstall (plugin_store.go:418) with code plugin_manifest_failed when an install whose InstallType is github-release completed but the InstallResult carries an empty ReleaseTag. Building a manifest from a release requires the tag; without it ManifestFromRelease cannot proceed.","triggerScenarios":"A custom pluginstore.Client implementation returning InstallType 'github_release' without setting ReleaseTag; an upstream installer code path that forgets to populate result.ReleaseTag after a successful install. Not caused by user input directly.","commonSituations":"Embedding the SDK with a hand-written Client; version drift between the management handlers and a vendored pluginstore package whose InstallResult semantics changed.","solutions":["If you implement pluginstore.Client, always set result.ReleaseTag to the tag you installed from before returning success","Upgrade the pluginstore package and management handlers together so InstallResult fields stay aligned","Retry the install — a stock client normally populates the tag, so a one-off empty tag suggests a partially failed install"],"exampleFix":"// before: custom client omits the tag\nreturn pluginstore.InstallResult{Version: v, InstallType: pluginstore.InstallTypeGitHubRelease}, nil\n\n// after: populate ReleaseTag\nreturn pluginstore.InstallResult{\n\tVersion:     v,\n\tInstallType: pluginstore.InstallTypeGitHubRelease,\n\tReleaseTag:  tag,\n}, nil","handlingStrategy":"validation","validationCode":"// Custom client: validate the result before returning it to the manifest step.\nif result.InstallType == pluginstore.InstallTypeGitHubRelease && strings.TrimSpace(result.ReleaseTag) == \"\" {\n\treturn pluginstore.InstallResult{}, fmt.Errorf(\"release tag missing in install result\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When implementing pluginstore.Client, always populate ReleaseTag for github-release installs","Upgrade vendored pluginstore packages in lockstep with the management handlers","Add unit tests asserting the result fields your manifest step depends on"],"tags":["plugins","plugin-store","manifest","sdk","github-release"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}