router-for-me/CLIProxyAPI · error
direct install plugin %q version %q resolved as %q
Error message
direct install plugin %q version %q resolved as %q
What it means
Returned from directPluginVersion when the requested version matches one of the plugin's historical entries in plugin.Versions, but that candidate's install plan (after NormalizeInstallPlan, with empty type defaulted to direct) resolves to a non-direct install type. Per-version install metadata overrides the plugin-level type, and a non-direct candidate cannot be used for direct install.
Source
Thrown at internal/pluginstore/install.go:233
plugin.Version = version
plugin.Install = NormalizeInstallPlan(plugin.Install)
plugin.Install.Type = InstallTypeDirect
if errPlan := ValidateInstallPlan(plugin.Install); errPlan != nil {
return Plugin{}, fmt.Errorf("direct install plugin %q version %q: %w", id, version, errPlan)
}
return plugin, nil
}
for _, candidate := range plugin.Versions {
if normalizeVersion(candidate.Version) != version {
continue
}
plugin.Version = version
plugin.Install = NormalizeInstallPlan(candidate.Install)
if plugin.Install.Type == "" {
plugin.Install.Type = InstallTypeDirect
}
if plugin.Install.Type != InstallTypeDirect {
return Plugin{}, fmt.Errorf("direct install plugin %q version %q resolved as %q", id, version, plugin.Install.Type)
}
if errPlan := ValidateInstallPlan(plugin.Install); errPlan != nil {
return Plugin{}, fmt.Errorf("direct install plugin %q version %q: %w", id, version, errPlan)
}
return plugin, nil
}
return Plugin{}, fmt.Errorf("direct install plugin %q version %q not found in source", id, version)
}
func InstallArchive(archiveData []byte, plugin Plugin, options InstallOptions) (InstallResult, error) {
options = normalizeInstallOptions(options)
id := strings.TrimSpace(plugin.ID)
if !validPluginID(id) {
return InstallResult{}, fmt.Errorf("invalid plugin id %q", plugin.ID)
}
version := normalizeVersion(plugin.Version)
if !validPluginVersion(version) {
return InstallResult{}, fmt.Errorf("invalid plugin version %q", plugin.Version)View on GitHub (pinned to 78f0c4079e)
Solutions
- Request a version whose registry entry is published with direct install type
- Update the registry's version entry to install type "direct" with direct artifacts
- Use the install API matching that version's published type
Example fix
// before manifest.Version = "0.9.0" // registry: versions[0.9.0].install.type = "github-release" plugin, err := client.ResolveDirect(ctx, manifest) // after manifest.Version = "1.0.0" // direct-type version plugin, err := client.ResolveDirect(ctx, manifest)
Defensive patterns
Strategy: validation
Validate before calling
func versionIsDirectType(plugin pluginstore.Plugin, version string) bool {
v := strings.TrimPrefix(strings.TrimPrefix(strings.TrimSpace(version), "v"), "V")
for _, cand := range plugin.Versions {
if strings.TrimPrefix(strings.TrimSpace(cand.Version), "v") == v {
return pluginstore.PluginInstallType(pluginstore.Plugin{Install: cand.Install}) == pluginstore.InstallTypeDirect || strings.TrimSpace(string(cand.Install.Type)) == ""
}
}
return false
} Type guard
func isVersionTypeMismatch(err error) bool {
return err != nil && strings.Contains(err.Error(), "version") && strings.Contains(err.Error(), "resolved as")
} Try / catch
if err != nil {
if isVersionTypeMismatch(err) {
// pick another version or the matching install path
}
} Prevention
- Keep install type consistent across all published versions of a plugin
- When migrating distribution models, re-publish old versions under the new type
- Expose available versions and their types to version-pinning users
When it happens
Trigger: Requested version found only in plugin.Versions with install.type explicitly set to "github-release" (or another type) while the caller asked for direct install; mixed-type version history in the registry.
Common situations: Older versions of a plugin published via GitHub releases while newer ones are direct; registry migration that left legacy version entries with the old install type; requesting a pinned legacy version from a plugin that has since moved to direct distribution.
Related errors
- direct install plugin %q resolved as %q
- direct install plugin %q version %q not found in source
- fetch direct install source: %w
- direct install plugin %q not found in source
- direct install plugin %q version %q: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/e62a623a9b45c323.
Report an issue: GitHub.