musistudio/claude-code-router · error · Error

Grok CLI OIDC discovery returned HTTP ${response.status}${to

Error message

Grok CLI OIDC discovery returned HTTP ${response.status}${tokenRefreshErrorMessage(payload, text)}

What it means

During Grok OIDC discovery, the well-known configuration endpoint returned a non-2xx status. The message includes the status code and any parseable error detail, thrown before a token endpoint can be resolved for the refresh flow.

Source

Thrown at packages/core/src/agents/local-providers/grok.ts:749

async function grokTokenEndpoint(auth: GrokTokenSet): Promise<string> {
  const configured = readString(process.env.GROK_OIDC_TOKEN_ENDPOINT);
  if (configured) {
    return configured;
  }
  const issuer = (auth.oidcIssuer || readString(process.env.GROK_OIDC_ISSUER) || grokDefaultOidcIssuer).replace(/\/+$/, "");
  const metadataUrl = `${issuer}/.well-known/openid-configuration`;
  const timeoutMs = normalizeGrokOauthTimeout(process.env.GROK_OIDC_REFRESH_TIMEOUT_MS);
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    const response = await fetchWithSystemProxy(metadataUrl, {
      headers: { accept: "application/json" },
      signal: controller.signal
    });
    const text = await response.text();
    const payload = parseJsonRecord(text);
    if (!response.ok) {
      throw new Error(`Grok CLI OIDC discovery returned HTTP ${response.status}${tokenRefreshErrorMessage(payload, text)}`);
    }
    const tokenEndpoint = readString(payload?.token_endpoint) || readString(payload?.tokenEndpoint);
    if (!tokenEndpoint) {
      throw new Error("Grok CLI OIDC discovery did not return a token endpoint.");
    }
    return tokenEndpoint;
  } catch (error) {
    if (error instanceof Error && error.name === "AbortError") {
      throw new Error(`Grok CLI OIDC discovery timed out after ${timeoutMs}ms.`);
    }
    throw error;
  } finally {
    clearTimeout(timer);
  }
}

function grokCredentialFiles(): string[] {
  const explicitFile = process.env.GROK_AUTH_FILE?.trim();

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Re-run login to refresh the cached discovery/issuer URL
  2. curl the discovery URL to confirm what status the host returns
  3. Check for proxy/VPN interference on the discovery host
  4. Retry — 5xx discovery failures are often transient
Defensive patterns

Strategy: retry

Validate before calling

const discoveryOk = await fetch(discoveryUrl, { method: 'HEAD' }).then(r => r.ok).catch(() => false);
if (!discoveryOk) deferProviderImport();

Try / catch

catch (e) {
  if (e instanceof Error && e.message.startsWith('Grok CLI OIDC discovery returned HTTP')) {
    const status = Number(e.message.match(/HTTP (\d+)/)?.[1]);
    if (status >= 500 || status === 429) await retryWithBackoff();
    else await refreshDiscoveryConfig();
  }
}

Prevention

When it happens

Trigger: fetching the OIDC discovery/well-known URL returns !response.ok — wrong/rotated discovery URL, 404 from a host that no longer serves discovery, or a 5xx during provider outage.

Common situations: The provider changed its OIDC issuer/host and cached configuration points to the old URL; regional endpoints differ; a proxy returns 407/502 for the discovery host.

Related errors


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