router-for-me/CLIProxyAPI · error

direct install plugin %q version %q not found in source

Error message

direct install plugin %q version %q not found in source

What it means

Terminal error from directPluginVersion: the requested version matches neither the plugin's top-level version nor any entry in plugin.Versions (comparison is done after normalizeVersion, so 'v' prefixes are ignored). The plugin exists in the source registry but that specific version does not.

Source

Thrown at internal/pluginstore/install.go:240

	}
	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)
	}
	plugin.Version = version
	reader, errZip := zip.NewReader(bytes.NewReader(archiveData), int64(len(archiveData)))
	if errZip != nil {
		return InstallResult{}, fmt.Errorf("open zip: %w", errZip)
	}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Fetch the registry and list the plugin's available versions (top-level Version plus Versions[]) to confirm what exists
  2. Update the requested manifest.Version to a published version
  3. Refresh/re-point the registry (SourceURL or Client.RegistryURL) if it is stale relative to upstream releases

Example fix

// before
manifest.Version = "2.0.0" // only 1.0.0, 1.1.0 published
plugin, err := client.ResolveDirect(ctx, manifest)

// after
manifest.Version = "1.1.0"
plugin, err := client.ResolveDirect(ctx, manifest)
Defensive patterns

Strategy: validation

Validate before calling

func versionPublished(reg pluginstore.Registry, id, version string) bool {
    p, ok := reg.PluginByID(strings.TrimSpace(id))
    if !ok {
        return false
    }
    norm := func(v string) string { return strings.TrimPrefix(strings.TrimSpace(v), "v") }
    if norm(p.Version) == norm(version) {
        return true
    }
    for _, cand := range p.Versions {
        if norm(cand.Version) == norm(version) {
            return true
        }
    }
    return false
}

Type guard

func isVersionNotFoundInSource(err error) bool {
    return err != nil && strings.Contains(err.Error(), "not found in source")
}

Try / catch

if err != nil {
    if isVersionNotFoundInSource(err) {
        // enumerate published versions and suggest the closest match
    }
}

Prevention

When it happens

Trigger: Requesting a version like "2.0.0" when the registry only has "1.x" entries; typo in the version string; version exists in a different registry than the one at SourceURL; manifest written against a newer registry state than the deployed one.

Common situations: Registry lag: plugin released upstream but the consumed registry snapshot is stale; pinning to a version that was never published or was yanked; environments pointing at different registries (staging has it, prod does not).

Related errors


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