musistudio/claude-code-router · error · Error

Grok CLI OIDC discovery did not return a token endpoint.

Error message

Grok CLI OIDC discovery did not return a token endpoint.

What it means

OIDC discovery for Grok succeeded at the HTTP level but the returned JSON lacked a token_endpoint (or tokenEndpoint) string, so no OAuth token URL could be derived. The library throws instead of guessing an endpoint.

Source

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

  }
  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();
  return uniqueStrings([
    explicitFile,
    path.join(grokStorageRoot(), "auth.json"),
    path.join(grokStorageRoot(), "credentials.json")

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Fetch the discovery URL manually and inspect the JSON for token_endpoint
  2. Re-run login to regenerate the cached discovery URL
  3. Verify the issuer matches the actual OIDC provider host
  4. Report if the provider changed the discovery schema
Defensive patterns

Strategy: validation

Validate before calling

const doc = await fetch(discoveryUrl).then(r => r.json());
if (typeof doc.token_endpoint !== 'string' || !doc.token_endpoint) {
  throw new Error('discovery document lacks token_endpoint — refresh login config');
}

Try / catch

catch (e) {
  if (e instanceof Error && e.message.includes('did not return a token endpoint')) {
    await relogin(); // cached discovery URL is wrong
  }
}

Prevention

When it happens

Trigger: The discovery document JSON parses but has no token_endpoint/tokenEndpoint field — a truncated body, a non-standard discovery document, or the URL pointing at a JSON resource that is not an OIDC configuration.

Common situations: Discovery URL points at the wrong well-known path; provider ships a partial/preview document; a proxy rewrites the response body.

Related errors


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