nexu-io/open-design · error · Error

token endpoint response missing access_token

Error message

token endpoint response missing access_token

What it means

exchangeCodeForToken received a 2xx but the JSON body has no access_token, which a conformant token endpoint must return. Its absence on a success status means a non-standard, errored, or envelope-wrapped response.

Source

Thrown at apps/daemon/src/mcp-oauth.ts:430

    // client_id we already put in the form. Public clients (PKCE-only)
    // skip this branch.
    const basic = Buffer.from(`${form.get('client_id')}:${clientSecret}`).toString('base64');
    headers['authorization'] = `Basic ${basic}`;
  }
  const res = await fetchImpl(tokenEndpoint, {
    method: 'POST',
    headers,
    body: form.toString(),
  });
  if (!res.ok) {
    const txt = await safeText(res);
    throw new Error(
      `token endpoint rejected request: HTTP ${res.status} ${res.statusText} ${txt}`,
    );
  }
  const json = (await res.json()) as OAuthTokenResponse;
  if (!json.access_token) {
    throw new Error('token endpoint response missing access_token');
  }
  return json;
}

async function safeText(res: Response): Promise<string> {
  try {
    const t = await res.text();
    return t.slice(0, 500);
  } catch {
    return '';
  }
}

// ───────────────────────────────────────────────────────────────────────
// In-memory pending-state cache.
// ───────────────────────────────────────────────────────────────────────

/**

View on GitHub (pinned to 5be4028344)

Solutions

  1. Inspect the raw token response body.
  2. If the provider wraps tokens, add compatibility handling or pre-register a client.
  3. Confirm you are hitting the true token_endpoint.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await exchangeCodeForToken(tokenEndpoint, params);
} catch (e) {
  if (/missing access_token/i.test(e.message)) {
    // inspect raw token body; restart beginAuth if the response is malformed
    return beginAuth(input);
  }
  throw e;
}

Prevention

When it happens

Trigger: Provider returned 200 with an error body; returned a wrapped or envelope schema; returned a refresh-only or empty payload.

Common situations: A non-conformant provider; an intermediate proxy rewrote the response.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/6bd4982968191fb1. Report an issue: GitHub.