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, nil

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. If you implement pluginstore.Client, always set result.ReleaseTag to the tag you installed from before returning success
  2. Upgrade the pluginstore package and management handlers together so InstallResult fields stay aligned
  3. 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 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


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/2b7e0079712cc4c2. Report an issue: GitHub.