router-for-me/CLIProxyAPI · error

invalid plugin store url

Error message

invalid plugin store url

What it means

validatePluginStoreRequestURL rejected a plugin store URL: url.Parse failed, or the parsed URL has no scheme or no host. The pluginstore client refuses to fetch registry/metadata/artifact resources from URLs it cannot positively identify, as a precondition before any auth or HTTP work. Typical causes are malformed URLs, missing https://, or a variable that expanded to a partial string.

Source

Thrown at internal/pluginstore/auth.go:313

		headers.Set("Authorization", "Basic "+encoded)
	case AuthTypeHeader:
		if strings.TrimSpace(item.HeaderName) == "" {
			return false, fmt.Errorf("plugin store resolved auth missing header-name")
		}
		if len(item.HeaderValue) == 0 {
			return false, fmt.Errorf("plugin store resolved auth header value is empty")
		}
		headers.Set(item.HeaderName, string(item.HeaderValue))
	default:
		return false, fmt.Errorf("unsupported plugin store resolved auth type %q", item.Type)
	}
	return true, nil
}

func validatePluginStoreRequestURL(auth []AuthConfig, requestURL string, kind string) error {
	parsed, errParse := url.Parse(strings.TrimSpace(requestURL))
	if errParse != nil || parsed.Scheme == "" || parsed.Host == "" {
		return fmt.Errorf("invalid plugin store url")
	}
	if parsed.User != nil {
		return fmt.Errorf("plugin store url must not contain credentials")
	}
	if hasSensitiveQueryParameter(parsed) {
		return fmt.Errorf("plugin store url contains sensitive query parameter")
	}
	if strings.EqualFold(parsed.Scheme, "http") && !allowInsecurePluginStoreURL(auth, requestURL, kind) {
		return fmt.Errorf("insecure plugin store url requires matching allow-insecure auth rule")
	}
	return nil
}

func allowInsecurePluginStoreURL(auth []AuthConfig, requestURL string, kind string) bool {
	item, ok := matchingAuthConfig(auth, requestURL, kind)
	return ok && item.AllowInsecure
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Write the full absolute URL including scheme and host, e.g. https://plugins.example.com/registry.json
  2. Print/inspect the effective URL at runtime to catch empty variable substitution
  3. Validate store URLs with url.Parse in a pre-flight check before configuring

Example fix

# before
url: plugins.example.com/plugins/index.json

# after
url: https://plugins.example.com/plugins/index.json
Defensive patterns

Strategy: validation

Validate before calling

func validStoreURL(raw string) error {
	u, err := url.Parse(strings.TrimSpace(raw))
	if err != nil || u.Scheme == "" || u.Host == "" {
		return fmt.Errorf("store URL %q must be absolute with scheme and host", raw)
	}
	return nil
}

Prevention

When it happens

Trigger: Calling a store fetch (registry.json, metadata, artifact download) with a URL like 'plugins.example.com/index.json' (no scheme), 'https:///path' (no host), or a value containing characters that make url.Parse error.

Common situations: Registry URL copied without the scheme; template variable for the store base URL empty so the path alone remains; trailing control characters or spaces beyond trimming; custom plugin store configured by hand in config.yaml.

Related errors


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