mastra-ai/mastra · error
Invalid device code response
Error message
Invalid device code response
What it means
`startDeviceFlow` validates that the GitHub device-code endpoint returned a JSON object before reading fields. If the response parsed as JSON but was not an object (or was empty), the SDK throws this error. It indicates the endpoint responded successfully (HTTP ok) but with an unexpected payload, usually because the URL does not actually serve the GitHub device-flow API.
Source
Thrown at mastracode/sdk/src/auth/providers/github-copilot.ts:139
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',
}),
},
signal,
);
if (!data || typeof data !== 'object') {
throw new Error('Invalid device code response');
}
const obj = data as Record<string, unknown>;
const deviceCode = obj.device_code;
const userCode = obj.user_code;
const verificationUri = obj.verification_uri;
const interval = obj.interval;
const expiresIn = obj.expires_in;
if (
typeof deviceCode !== 'string' ||
typeof userCode !== 'string' ||
typeof verificationUri !== 'string' ||
typeof interval !== 'number' ||
typeof expiresIn !== 'number'
) {
throw new Error('Invalid device code response fields');
}View on GitHub (pinned to 75dd419e61)
Solutions
- Verify the GitHub domain config — the resolved `deviceCodeUrl` must be `https://<github.com or GHES host>/login/device/code`
- Log/print the raw response body of the device-code request to see what was actually returned
- Bypass or correctly configure proxies/SSL inspection that rewrite GitHub responses
- Test the endpoint directly with curl to confirm it returns a JSON object with device_code
- If on GHES, confirm Copilot/OAuth device flow is enabled on that instance
Example fix
// before: misconfigured domain leads to unexpected response
const provider = createGitHubCopilotProvider({ domain: 'github.mycompany.com' });
// after: verify the correct GitHub host (GHES base host, not api. subdomain)
const provider = createGitHubCopilotProvider({ domain: 'github.example.com' }); // if that is the real GHES host
curl -i https://github.example.com/login/device/code -d 'client_id=...&scope=read:user' // confirm JSON object Defensive patterns
Strategy: type-guard
Validate before calling
// Sanity-check the endpoint returns a JSON object before the SDK consumes it
const probe = await fetch(deviceCodeUrl, { method: 'POST', headers: { Accept: 'application/json' }, body: new URLSearchParams({ client_id: 'Iv1.b507a08c87ecfe98', scope: 'read:user' }) });
const probeBody = await probe.json().catch(() => null);
if (!probeBody || typeof probeBody !== 'object' || Array.isArray(probeBody)) throw new Error(`Unexpected device-code payload from ${deviceCodeUrl}`); Type guard
function isDeviceCodeResponse(v: unknown): v is { device_code: string; user_code: string; verification_uri: string; interval: number; expires_in: number } {
if (!v || typeof v !== 'object' || Array.isArray(v)) return false;
const o = v as Record<string, unknown>;
return typeof o.device_code === 'string' && typeof o.user_code === 'string' && typeof o.verification_uri === 'string' && typeof o.interval === 'number' && typeof o.expires_in === 'number';
} Try / catch
try {
const pending = await provider.device();
} catch (e) {
if (e instanceof Error && e.message === 'Invalid device code response') {
console.error('Device-code endpoint did not return a JSON object. Check the configured GitHub domain/proxy:', e.message);
return reconfigureDomainOrProxy();
}
throw e;
} Prevention
- Pin and verify the GitHub/GHES domain; test /login/device/code with curl during setup
- Bypass or correctly configure corporate proxies and SSL inspection for github.com hosts
- Wrap provider.device() so unexpected payloads are logged verbatim before failing
- On GHES, confirm the OAuth device-flow feature is enabled and its API version
When it happens
Trigger: The device-code URL returned 200 with an empty body, an array, a string, or an HTML/login page that fetch's `response.json()` accepted (rare) — e.g. a GHES domain whose `getUrls` produced a wrong `deviceCodeUrl`, or an intermediate proxy/gateway returning an ok response with a non-JSON-object body.
Common situations: Typo'd or outdated enterprise domain in config pointing at a page/proxy instead of the OAuth endpoints, a corporate proxy intercepting github.com, or a GitHub API change/version where the endpoint shape differs.
Related errors
- ${response.status} ${response.statusText}: ${text}
- Invalid device code response fields
- Invalid Copilot token response
- Kimi For Coding device authorization failed: ${response.stat
- Token exchange failed: ${error}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/0e21df683e3761e6.
Report an issue: GitHub.