{"record":{"id":"fc7b3ea03c8677e7","repo":"router-for-me/CLIProxyAPI","slug":"direct-install-plugin-q-not-found-in-source","errorCode":null,"errorMessage":"direct install plugin %q not found in source","messagePattern":"direct install plugin %q not found in source","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginstore/install.go","lineNumber":203,"sourceCode":"\tif len(plugin.Install.Artifacts) > 0 {\n\t\treturn plugin, nil\n\t}\n\tsourceURL := strings.TrimSpace(manifest.SourceURL)\n\tif sourceURL == \"\" {\n\t\tsourceURL = strings.TrimSpace(c.RegistryURL)\n\t}\n\tif sourceURL == \"\" {\n\t\treturn Plugin{}, fmt.Errorf(\"direct install manifest missing source-url\")\n\t}\n\tsourceClient := c\n\tsourceClient.RegistryURL = sourceURL\n\tregistry, errRegistry := sourceClient.FetchRegistry(ctx)\n\tif errRegistry != nil {\n\t\treturn Plugin{}, fmt.Errorf(\"fetch direct install source: %w\", errRegistry)\n\t}\n\tresolved, okPlugin := registry.PluginByID(manifest.ID)\n\tif !okPlugin {\n\t\treturn Plugin{}, fmt.Errorf(\"direct install plugin %q not found in source\", strings.TrimSpace(manifest.ID))\n\t}\n\tif PluginInstallType(resolved) != InstallTypeDirect {\n\t\treturn Plugin{}, fmt.Errorf(\"direct install plugin %q resolved as %q\", strings.TrimSpace(manifest.ID), PluginInstallType(resolved))\n\t}\n\treturn directPluginVersion(resolved, manifest.ID, manifest.Version)\n}\n\nfunc directPluginVersion(plugin Plugin, id string, version string) (Plugin, error) {\n\tid = strings.TrimSpace(id)\n\tversion = normalizeVersion(version)\n\tif normalizeVersion(plugin.Version) == version {\n\t\tplugin.Version = version\n\t\tplugin.Install = NormalizeInstallPlan(plugin.Install)\n\t\tplugin.Install.Type = InstallTypeDirect\n\t\tif errPlan := ValidateInstallPlan(plugin.Install); errPlan != nil {\n\t\t\treturn Plugin{}, fmt.Errorf(\"direct install plugin %q version %q: %w\", id, version, errPlan)\n\t\t}\n\t\treturn plugin, nil","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/install.go#L185-L221","documentation":"Returned during direct-install resolution when the registry was fetched successfully from the source URL but registry.PluginByID(manifest.ID) finds no entry with that ID. The manifest references a plugin the source registry does not know about. The library treats this as a hard mismatch because it cannot construct artifact coordinates for an unknown plugin.","triggerScenarios":"manifest.ID is trimmed and looked up in the source registry; mismatch happens when the plugin was renamed, removed from the registry, the manifest was written against a different registry, or the ID has a typo/case difference.","commonSituations":"Plugin renamed upstream but local manifests still use the old ID; pointing SourceURL at the wrong registry (staging vs production); trailing whitespace or case differences in the ID; plugin deprecated and pruned from the registry; typo in a hand-edited manifest.","solutions":["Fetch the registry document and confirm the exact plugin ID exists (compare case and spelling verbatim)","Update manifest.ID to the current ID published by the source registry","Point manifest.SourceURL at the registry that actually hosts the plugin"],"exampleFix":"// before\nmanifest.ID = \"example-plugin \" // trailing space or wrong name\n\n// after\nmanifest.ID = \"example-plugin\" // exact ID as published in the source registry\nplugin, err := client.ResolveDirect(ctx, manifest)","handlingStrategy":"validation","validationCode":"func pluginExistsInRegistry(ctx context.Context, c pluginstore.Client, id string) (bool, error) {\n    reg, err := c.FetchRegistry(ctx)\n    if err != nil {\n        return false, err\n    }\n    _, ok := reg.PluginByID(strings.TrimSpace(id))\n    return ok, nil\n}","typeGuard":"func isPluginNotFoundInSource(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"not found in source\")\n}","tryCatchPattern":"if err := client.ResolveDirect(ctx, manifest); err != nil {\n    if isPluginNotFoundInSource(err) {\n        // surface actionable message: list available IDs from FetchRegistry\n    }\n}","preventionTips":["Validate manifest IDs against the registry before distributing manifests","Trim and canonicalize IDs (case, whitespace) at authoring time","Subscribe to registry change notices so renames/removals are caught early"],"tags":["go","plugin-store","registry","manifest","lookup"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}