musistudio/claude-code-router · error · Error

Unsupported provider protocol: ${value}

Error message

Unsupported provider protocol: ${value}

What it means

normalizeProviderProtocol validates an optional protocol field on provider deep links/manifests against the known GatewayProviderProtocol set (providerProtocols). An unrecognized protocol string (e.g. 'openai-completions' when only specific values are supported) throws with the offending value embedded.

Source

Thrown at packages/core/src/contracts/deep-link.ts:497

  const url = new URL(value);
  if (url.protocol !== "https:") {
    throw new Error("Provider manifest URL must use https.");
  }
  if (url.username || url.password) {
    throw new Error("Provider manifest URL cannot include credentials.");
  }
  if (!url.hostname) {
    throw new Error("Provider manifest URL is invalid.");
  }
}

function normalizeProviderProtocol(value: string | undefined): GatewayProviderProtocol | undefined {
  if (!value) {
    return undefined;
  }
  const protocol = value.trim();
  if (!providerProtocols.has(protocol as GatewayProviderProtocol)) {
    throw new Error(`Unsupported provider protocol: ${value}`);
  }
  return protocol as GatewayProviderProtocol;
}

function readDeepLinkModels(params: URLSearchParams, payload: Record<string, unknown> | undefined): string[] {
  const values = [
    ...params.getAll("models"),
    ...payloadModels(payload)
  ];
  const seen = new Set<string>();
  const models: string[] = [];

  for (const value of values) {
    for (const model of splitModelValue(value)) {
      if (model.length > maxModelLength) {
        throw new Error("Model name is too long.");
      }
      if (seen.has(model)) {

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Use only the protocol identifiers exported/supported by the current version (check the GatewayProviderProtocol type / providerProtocols set)
  2. Omit protocol to use the default rather than guessing a value
  3. Upgrade the library if a newly added provider protocol should be supported

Example fix

// before
{"provider":{"protocol":"openai-chat-completions","base_url":"..."}}
// after
{"provider":{"protocol":"openai","base_url":"..."}}
Defensive patterns

Strategy: type-guard

Validate before calling

const known = new Set(["openai", "anthropic", ...]); if (protocol && !known.has(protocol)) return useDefault();

Type guard

const isSupportedProtocol = (v: string | undefined, known: ReadonlySet<string>): v is string => !v || known.has(v.trim());

Try / catch

try { parseProviderDeepLinkPayload(url); } catch (e) { if (e instanceof Error && e.message.startsWith("Unsupported provider protocol")) return fallbackToDefaultProtocol(); throw e; }

Prevention

When it happens

Trigger: Passing protocol="anthropic-beta" or any string not in providerProtocols in a ccr:// link or provider manifest.

Common situations: Providers adding new protocol identifiers before this library supports them; typos/casing differences ('OpenAI' vs 'openai'); manifests written against a different gateway's schema.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/e059a4df597ba1fe. Report an issue: GitHub.