mastra-ai/mastra · error
${response.status} ${response.statusText}: ${text}
Error message
${response.status} ${response.statusText}: ${text} What it means
This is the generic HTTP failure thrown by the SDK's GitHub Copilot auth `fetchJson` helper whenever the GitHub OAuth/device-code or Copilot token endpoint returns a non-2xx response. The message embeds the HTTP status, status text, and the raw response body, so it directly reflects what the GitHub server rejected. It surfaces during device-flow login (`startDeviceFlow`, token polling) and Copilot bearer-token refresh.
Source
Thrown at mastracode/sdk/src/auth/providers/github-copilot.ts:114
/**
* Resolve the Copilot API base URL.
* Prefers the `proxy-ep` parsed from the bearer token, then falls back to enterprise/individual defaults.
*/
export function getGitHubCopilotBaseUrl(token?: string, enterpriseDomain?: string): string {
if (token) {
const fromToken = getBaseUrlFromToken(token);
if (fromToken) return fromToken;
}
if (enterpriseDomain) return `https://copilot-api.${enterpriseDomain}`;
return 'https://api.individual.githubcopilot.com';
}
async function fetchJson(url: string, init: RequestInit, signal?: AbortSignal): Promise<unknown> {
const response = await fetch(url, signal ? { ...init, signal } : init);
if (!response.ok) {
const text = await response.text().catch(() => '');
throw new Error(`${response.status} ${response.statusText}: ${text}`);
}
return response.json();
}
async function startDeviceFlow(domain: string, signal?: AbortSignal): Promise<DeviceCodeResponse> {
const urls = getUrls(domain);
const data = await fetchJson(
urls.deviceCodeUrl,
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': COPILOT_USER_AGENT,
},
body: new URLSearchParams({
client_id: CLIENT_ID,
scope: 'read:user',View on GitHub (pinned to 75dd419e61)
Solutions
- Read the status and body in the message: `authorization_pending`/`slow_down` bodies mean keep polling — ensure your caller tolerates these instead of crashing
- Verify the configured GitHub domain (github.com vs your GHES hostname) — a wrong domain produces 404/SSL errors
- Check network/proxy reachability to github.com and api.github.com and retry 5xx/429 with backoff
- If 401/403 on the Copilot token endpoint, redo the full device-flow login to obtain a fresh GitHub OAuth token
- Confirm the SDK's client_id/endpoint config matches the installed version if the API contract changed
Example fix
// before: treating every non-ok response as fatal, even during polling
const creds = await provider.device(); // throws on authorization_pending
// after: catch and branch on the pending/slow-down bodies
try {
const creds = await provider.device();
} catch (e) {
const m = String((e as Error).message);
if (m.includes('authorization_pending') || m.includes('slow_down')) {
await sleep(intervalMs);
return; // keep polling
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Precheck connectivity and domain before calling the provider
async function canReach(url: string): Promise<boolean> {
try { const r = await fetch(url, { method: 'HEAD' }); return r.status < 500 || r.status !== 404; } catch { return false; }
}
await canReach('https://github.com/login/device/code'); Type guard
function isHttpErrorWithStatus(e: unknown): e is Error & { message: string } {
return e instanceof Error && /^\d{3} /.test(e.message);
}
function parseStatus(msg: string): number | null {
const m = /^(\d{3}) /.exec(msg);
return m ? Number(m[1]) : null;
} Try / catch
try {
const creds = await provider.device();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
const status = parseStatus(msg);
if (status === 429 || (status ?? 500) >= 500) { await backoff(); return retry(); }
if (msg.includes('authorization_pending') || msg.includes('slow_down')) { await sleep(intervalMs); return; }
if (status === 401 || status === 403) { return startFreshDeviceFlow(); }
throw e;
} Prevention
- Handle authorization_pending/slow_down bodies as part of normal device-flow polling, not fatal errors
- Validate the GitHub domain config (github.com vs GHES host) before login
- Apply exponential backoff on 5xx/429 responses
- Monitor for 401/403 on token refresh and trigger re-login proactively
- Log the embedded response body from the error message for GitHub-side diagnostics
When it happens
Trigger: Any non-ok response from `POST https://github.com/login/device/code`, `POST .../login/oauth/access_token`, or `POST https://api.<domain>/copilot_internal/v2/token` — e.g. 401 after the user denied the device flow, 400 from a wrong `client_id` or malformed body, 404/redirect from an incorrect enterprise domain, 429 slow-down during polling, 5xx from GitHub.
Common situations: Polling `access_token` before the user finishes entering the device code (expected `authorization_pending` 400s surfaced as this error if not handled), misconfigured GHES/GHE domain so URLs point at the wrong host, expired or revoked GitHub OAuth grant during token refresh, corporate proxy or rate limiting returning 403/429.
Related errors
- Invalid device code response
- Kimi For Coding device authorization failed: ${response.stat
- Slack OAuth HTTP error: ${tokenResponse.status} ${tokenRespo
- GitHub OAuth token exchange failed: ${res.status}
- Invalid device code response fields
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/5ea8b9b48d325bc4.
Report an issue: GitHub.