musistudio/claude-code-router · error · Error

Base URL is required.

Error message

Base URL is required.

What it means

parseProviderDeepLinkPayload requires a base URL: after reading base_url from the query params or the JSON/base64 payload record (bounded by maxBaseUrlLength), an empty/missing value throws. The base URL is the minimum required field to create a provider entry.

Source

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

    throw new Error("Unsupported CCR link target.");
  }

  const params = url.searchParams;
  const payload = readPayloadRecord(params);
  const name = boundedString(
    firstStringParam(params, ["name"]) ??
      firstPayloadString(payload, ["name"]),
    maxNameLength,
    "Provider name"
  );
  const baseUrl = boundedString(
    firstStringParam(params, ["base_url"]) ??
      firstPayloadString(payload, ["base_url"]),
    maxBaseUrlLength,
    "Base URL"
  );
  if (!baseUrl) {
    throw new Error("Base URL is required.");
  }
  validateProviderBaseUrl(baseUrl);

  const apiKey = boundedString(
    firstStringParam(params, ["api_key"]) ??
      firstPayloadString(payload, ["api_key"]),
    maxApiKeyLength,
    "API key"
  );
  const icon = boundedString(
    firstStringParam(params, ["icon"]) ??
      firstPayloadString(payload, ["icon"]),
    maxIconLength,
    "Provider icon"
  );
  const protocol = normalizeProviderProtocol(
    firstStringParam(params, ["protocol"]) ?? firstPayloadString(payload, ["protocol"])
  );

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Add base_url=<provider endpoint> to the link's query params or payload record
  2. Confirm the payload JSON uses snake_case base_url exactly
  3. Pre-validate with URLSearchParams(url).get('base_url') before calling the parser

Example fix

// before
const link = "ccr://provider/install?name=acme";
// after
const link = "ccr://provider/install?name=acme&base_url=https%3A%2F%2Fapi.acme.dev%2Fv1";
Defensive patterns

Strategy: validation

Validate before calling

const u = new URL(rawUrl.trim()); if (!u.searchParams.get("base_url")) return promptForBaseUrl();

Type guard

const hasBaseUrlParam = (u: string) => {
  const p = new URL(u.trim()).searchParams;
  return Boolean(p.get("base_url") ?? JSON.parse(p.get("payload") ?? "{}").base_url);
};

Try / catch

try { parseProviderDeepLinkPayload(url); } catch (e) { if (e instanceof Error && e.message === "Base URL is required.") return collectBaseUrlThen(url); throw e; }

Prevention

When it happens

Trigger: Calling parseProviderDeepLinkPayload with a ccr://provider link that has name= but no base_url= (neither in query nor payload), or base_url that is empty string / whitespace-trimmed to nothing.

Common situations: Hand-built links omitting base_url; payload JSON using a wrong key (baseUrl vs base_url); the field dropped by URL encoding bugs; user edited the link and removed the param.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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