router-for-me/CLIProxyAPI · error
plugin_manifest_failed
plugin_manifest_failed
Error message
release tag is required
What it means
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.
Source
Thrown at internal/api/handlers/management/plugin_store.go:418
errs = append(errs, fmt.Errorf("%s: %w", tag, errInstall))
}
return pluginstore.InstallResult{}, fmt.Errorf("install release by tag: %w", errors.Join(errs...))
}
func pluginStoreManifestForInstall(source pluginstore.Source, plugin pluginstore.Plugin, result pluginstore.InstallResult) (pluginstore.Manifest, error) {
installType := strings.TrimSpace(result.InstallType)
if installType == "" {
installType = pluginstore.PluginInstallType(plugin)
}
switch installType {
case pluginstore.InstallTypeDirect:
plugin.Version = strings.TrimSpace(result.Version)
plugin.Install = pluginstore.NormalizeInstallPlan(plugin.Install)
return pluginstore.ManifestFromPlugin(source, plugin)
case pluginstore.InstallTypeGitHubRelease:
releaseTag := strings.TrimSpace(result.ReleaseTag)
if releaseTag == "" {
return pluginstore.Manifest{}, fmt.Errorf("release tag is required")
}
return pluginstore.ManifestFromRelease(source, plugin, pluginstore.Release{TagName: releaseTag})
default:
return pluginstore.Manifest{}, fmt.Errorf("unsupported install type %q", result.InstallType)
}
}
func pluginInstallRequestedVersion(c *gin.Context) (string, error) {
requestedVersion := strings.TrimSpace(c.Query("version"))
if c == nil || c.Request == nil || c.Request.Body == nil || c.Request.Body == http.NoBody {
return requestedVersion, nil
}
body, errRead := io.ReadAll(c.Request.Body)
if errRead != nil {
return "", fmt.Errorf("read install request: %w", errRead)
}
if strings.TrimSpace(string(body)) == "" {
return requestedVersion, nilView on GitHub (pinned to 78f0c4079e)
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
Example fix
// before: custom client omits the tag
return pluginstore.InstallResult{Version: v, InstallType: pluginstore.InstallTypeGitHubRelease}, nil
// after: populate ReleaseTag
return pluginstore.InstallResult{
Version: v,
InstallType: pluginstore.InstallTypeGitHubRelease,
ReleaseTag: tag,
}, nil Defensive patterns
Strategy: validation
Validate before calling
// Custom client: validate the result before returning it to the manifest step.
if result.InstallType == pluginstore.InstallTypeGitHubRelease && strings.TrimSpace(result.ReleaseTag) == "" {
return pluginstore.InstallResult{}, fmt.Errorf("release tag missing in install result")
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Embedding the SDK with a hand-written Client; version drift between the management handlers and a vendored pluginstore package whose InstallResult semantics changed.
Related errors
- plugin_install_failed
- plugin_manifest_invalid
- invalid_request
- artifact exceeds declared size
- artifact checksum missing
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/2b7e0079712cc4c2.
Report an issue: GitHub.