musistudio/claude-code-router · error · Error

New API refresh response did not include an access token.

Error message

New API refresh response did not include an access token.

What it means

After the refresh call succeeds, refreshTokenFromPayload inspects the response for an access token; if none is found the connector cannot authenticate subsequent subscription calls and throws. The expected token location depends on the New API provider's response shape.

Source

Thrown at packages/electron/bundled-plugins/new-api-account/index.cjs:48

    throw new Error("New API provider base URL is missing.");
  }

  const timeoutMs = normalizeTimeoutMs(options.timeoutMs);
  const requestOrigin = readString(options.requestOrigin) || root;
  const refreshPayload = await request.fetchProviderAccountJson({
    body: options.refreshBody ?? {},
    credentials: "include",
    endpoint: rootUrl(root, readString(options.refreshPath) || DEFAULT_REFRESH_PATH),
    headers: readStringRecord(options.refreshHeaders),
    method: "POST",
    requestOrigin,
    timeoutMs
  });
  assertSuccessfulPayload(refreshPayload, "New API refresh");

  const token = refreshTokenFromPayload(refreshPayload);
  if (!token) {
    throw new Error("New API refresh response did not include an access token.");
  }

  const subscriptionPayload = await request.fetchProviderAccountJson({
    credentials: "omit",
    endpoint: rootUrl(root, readString(options.subscriptionPath) || DEFAULT_SUBSCRIPTION_PATH),
    headers: {
      ...readStringRecord(options.subscriptionHeaders),
      authorization: `Bearer ${token}`
    },
    method: "GET",
    requestOrigin,
    timeoutMs
  });
  assertSuccessfulPayload(subscriptionPayload, "New API subscription");

  const meter = subscriptionQuotaMeter(subscriptionPayload, options);
  return {
    message: subscriptionMessage(subscriptionPayload),

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Re-authenticate/renew the stored provider account credentials and retry
  2. Inspect the raw refresh response body to find where the token actually lives and update refreshTokenFromPayload mapping/options
  3. Confirm the refresh endpoint and refreshBody in options match the provider's API
  4. Check for proxy/SSO interception returning non-JSON

Example fix

// before
const token = refreshTokenFromPayload(refreshPayload);
if (!token) throw new Error('New API refresh response did not include an access token.');

// after
const token = refreshTokenFromPayload(refreshPayload)
  ?? readPath(payloadData(refreshPayload), ['data', 'access_token']);
if (!token) throw new Error('New API refresh response did not include an access token.');
Defensive patterns

Strategy: try-catch

Validate before calling

const token = refreshTokenFromPayload(refreshPayload);
if (!token) console.warn('refresh payload keys:', Object.keys(payloadData(refreshPayload)));

Type guard

null

Try / catch

try { token = refreshTokenFromPayload(refreshPayload); } catch { /* never thrown; guard below */ }
if (!token) { await reauthenticate(); return; }

Prevention

When it happens

Trigger: Provider returns 200 with a body lacking the token field (expired session, MFA challenge, HTML login page parsed as JSON, or a changed response schema).

Common situations: Expired/revoked credentials where the endpoint returns success without a token, provider version changed token field name, cookie-based auth not attached, or a proxy/CDN intercepting with an HTML error page.

Related errors


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