{"record":{"id":"fe36f9782605c7e5","repo":"router-for-me/CLIProxyAPI","slug":"direct-install-plugin-q-version-q-w","errorCode":null,"errorMessage":"direct install plugin %q version %q: %w","messagePattern":"direct install plugin %q version %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginstore/install.go","lineNumber":219,"sourceCode":"\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\n\t}\n\tfor _, candidate := range plugin.Versions {\n\t\tif normalizeVersion(candidate.Version) != version {\n\t\t\tcontinue\n\t\t}\n\t\tplugin.Version = version\n\t\tplugin.Install = NormalizeInstallPlan(candidate.Install)\n\t\tif plugin.Install.Type == \"\" {\n\t\t\tplugin.Install.Type = InstallTypeDirect\n\t\t}\n\t\tif plugin.Install.Type != InstallTypeDirect {\n\t\t\treturn Plugin{}, fmt.Errorf(\"direct install plugin %q version %q resolved as %q\", id, version, plugin.Install.Type)\n\t\t}\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}","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/install.go#L201-L237","documentation":"Wrapped error from directPluginVersion when the resolved plugin's TOP-LEVEL version exactly matches the requested version (normalizeVersion(plugin.Version) == version), so its Install plan is used directly, but ValidateInstallPlan rejects that plan. The id and requested version are included; the underlying validation failure (e.g. invalid/missing artifact entries) is chained via %w.","triggerScenarios":"Registry entry whose top-level version matches the requested one but whose install plan is invalid: zero usable artifacts, malformed artifact URLs, missing checksums, or an invalid plan type after NormalizeInstallPlan + forced InstallTypeDirect.","commonSituations":"Registry published with an incomplete artifacts list for the current version; artifact entries filtered out because they lack URLs; registry hand-edited and plan fields left blank; schema change in the registry format leaving plan fields unparsed.","solutions":["Unwrap the error and read the ValidateInstallPlan message to see which plan field is invalid","Fix the registry entry for that plugin/version: ensure the install plan has at least one well-formed artifact (URL + checksum) for the target platform","If the registry is remote, re-fetch it to rule out a stale cached copy"],"exampleFix":"// before: registry entry\n// { \"id\": \"p\", \"version\": \"1.0.0\", \"install\": { \"type\": \"direct\", \"artifacts\": [] } }\nplugin, err := client.ResolveDirect(ctx, manifest) // \"direct install plugin \\\"p\\\" version \\\"1.0.0\\\": ...\"\n\n// after\n// { \"id\": \"p\", \"version\": \"1.0.0\", \"install\": { \"type\": \"direct\", \"artifacts\": [\n//     { \"url\": \"https://cdn.example.com/p-1.0.0-linux-amd64.zip\", \"checksum\": \"sha256:...\", \"os\": \"linux\", \"arch\": \"amd64\" } ] } }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"plugin, err := client.ResolveDirect(ctx, manifest)\nif err != nil {\n    if strings.Contains(err.Error(), fmt.Sprintf(\"direct install plugin %q version %q:\", manifest.ID, manifest.Version)) {\n        cause := errors.Unwrap(err) // ValidateInstallPlan detail\n        return fmt.Errorf(\"registry install plan invalid for %s@%s: %w\", manifest.ID, manifest.Version, cause)\n    }\n    return err\n}","preventionTips":["Validate registry entries with a CI check that runs ValidateInstallPlan-equivalent rules on every publish","Require at least one artifact per target platform in the plan before publishing a version","Unwrap chained errors in logs so the real plan defect is visible"],"tags":["go","plugin-store","registry","install-plan","validation"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}