mastra-ai/mastra · error
Invalid Copilot token response fields
Error message
Invalid Copilot token response fields
What it means
After `refreshGitHubCopilotToken` confirms the Copilot token response is an object, it validates that `token` is a string and `expires_at` is a number (Unix seconds). Missing or mistyped fields mean the Copilot token endpoint returned ok but without the expected bearer-token payload, so the SDK refuses to build `GitHubCopilotCredentials`. This is defensive validation against API drift or partial responses.
Source
Thrown at mastracode/sdk/src/auth/providers/github-copilot.ts:357
headers: {
Accept: 'application/json',
Authorization: `Bearer ${refreshToken}`,
...COPILOT_HEADERS,
},
},
signal,
);
if (!raw || typeof raw !== 'object') {
throw new Error('Invalid Copilot token response');
}
const obj = raw as Record<string, unknown>;
const token = obj.token;
const expiresAt = obj.expires_at;
if (typeof token !== 'string' || typeof expiresAt !== 'number') {
throw new Error('Invalid Copilot token response fields');
}
const credentials: GitHubCopilotCredentials = {
refresh: refreshToken,
access: token,
// expires_at is seconds; subtract 5 minutes so we refresh before actual expiry.
expires: expiresAt * 1000 - 5 * 60 * 1000,
};
if (enterpriseDomain) {
credentials.enterpriseUrl = enterpriseDomain;
}
return credentials;
}
/**
* Login with GitHub Copilot OAuth (device-code flow).
*
* Prompts for an optional GitHub Enterprise URL/domain, performs the device-code flow,View on GitHub (pinned to 75dd419e61)
Solutions
- Log the parsed response object to identify which field is missing or mistyped
- Check for an error envelope (`message`, `documentation_url`) and re-authenticate via device flow if the GitHub token is no longer accepted
- If using GHES/Enterprise Copilot, verify the instance's `copilot_internal` API version matches what the SDK expects
- Update test fixtures/mocks to include both `token: string` and `expires_at: number` in seconds
- Upgrade the SDK after any GitHub internal API change so parsing matches the new shape
Example fix
// before: mock fixture missing fields breaks refresh
const body = { token: 'tid=...;exp=...;proxy-ep=...' };
// after: include the full expected payload with expires_at in seconds
const body = { token: 'tid=...;exp=1799999999;proxy-ep=proxy.individual.githubcopilot.com', expires_at: 1799999999 }; Defensive patterns
Strategy: type-guard
Validate before calling
// Confirm the token payload carries both required fields before passing it around
function hasCopilotTokenPayload(o: unknown): boolean {
const r = o as Record<string, unknown> | null;
return !!r && typeof r.token === 'string' && r.token.includes('proxy-ep=') && typeof r.expires_at === 'number' && r.expires_at > 0;
} Type guard
function isGitHubCopilotTokenPayload(v: unknown): v is { token: string; expires_at: number } {
if (!v || typeof v !== 'object') return false;
const o = v as Record<string, unknown>;
return typeof o.token === 'string' && o.token.length > 0 && typeof o.expires_at === 'number' && Number.isFinite(o.expires_at);
} Try / catch
try {
const creds = await provider.credentials();
} catch (e) {
if (e instanceof Error && e.message === 'Invalid Copilot token response fields') {
// Log the payload keys to see which field is missing or mistyped, then re-auth
console.error('Copilot token payload invalid:', e.message);
return startFreshDeviceFlow();
}
throw e;
} Prevention
- Treat a missing token/expires_at as an auth failure and trigger re-login, not infinite retries
- Fix test fixtures/mocks to include token: string and expires_at: number (Unix seconds)
- Track GitHub internal API changes; upgrade the SDK when the envelope evolves
- Cache and proactively refresh credentials ~5 minutes before expiry so refreshes are predictable
When it happens
Trigger: The `/copilot_internal/v2/token` endpoint returned an object missing `token` or `expires_at` (or with a string `expires_at`), e.g. an error envelope `{message:"..."}` served with 200, a GHES/Copilot-for-Enterprise endpoint with a different payload version, or a proxy serving cached/partial JSON.
Common situations: GitHub changing or versioning the internal token endpoint shape, GHE Copilot endpoints diverging from github.com, mock servers or MSW fixtures returning incomplete token objects during development/testing.
Related errors
- Invalid device code response fields
- Invalid Copilot token response
- Invalid device code response
- Invalid Copilot models response: missing `data` array
- No Copilot bearer token
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/9f38043ccd9c5b0b.
Report an issue: GitHub.