{"record":{"id":"0e21df683e3761e6","repo":"mastra-ai/mastra","slug":"invalid-device-code-response","errorCode":null,"errorMessage":"Invalid device code response","messagePattern":"Invalid device code response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/auth/providers/github-copilot.ts","lineNumber":139,"sourceCode":"  const data = await fetchJson(\n    urls.deviceCodeUrl,\n    {\n      method: 'POST',\n      headers: {\n        Accept: 'application/json',\n        'Content-Type': 'application/x-www-form-urlencoded',\n        'User-Agent': COPILOT_USER_AGENT,\n      },\n      body: new URLSearchParams({\n        client_id: CLIENT_ID,\n        scope: 'read:user',\n      }),\n    },\n    signal,\n  );\n\n  if (!data || typeof data !== 'object') {\n    throw new Error('Invalid device code response');\n  }\n\n  const obj = data as Record<string, unknown>;\n  const deviceCode = obj.device_code;\n  const userCode = obj.user_code;\n  const verificationUri = obj.verification_uri;\n  const interval = obj.interval;\n  const expiresIn = obj.expires_in;\n\n  if (\n    typeof deviceCode !== 'string' ||\n    typeof userCode !== 'string' ||\n    typeof verificationUri !== 'string' ||\n    typeof interval !== 'number' ||\n    typeof expiresIn !== 'number'\n  ) {\n    throw new Error('Invalid device code response fields');\n  }","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/auth/providers/github-copilot.ts#L121-L157","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: misconfigured domain leads to unexpected response\nconst provider = createGitHubCopilotProvider({ domain: 'github.mycompany.com' });\n// after: verify the correct GitHub host (GHES base host, not api. subdomain)\nconst provider = createGitHubCopilotProvider({ domain: 'github.example.com' }); // if that is the real GHES host\ncurl -i https://github.example.com/login/device/code -d 'client_id=...&scope=read:user' // confirm JSON object","handlingStrategy":"type-guard","validationCode":"// Sanity-check the endpoint returns a JSON object before the SDK consumes it\nconst probe = await fetch(deviceCodeUrl, { method: 'POST', headers: { Accept: 'application/json' }, body: new URLSearchParams({ client_id: 'Iv1.b507a08c87ecfe98', scope: 'read:user' }) });\nconst probeBody = await probe.json().catch(() => null);\nif (!probeBody || typeof probeBody !== 'object' || Array.isArray(probeBody)) throw new Error(`Unexpected device-code payload from ${deviceCodeUrl}`);","typeGuard":"function isDeviceCodeResponse(v: unknown): v is { device_code: string; user_code: string; verification_uri: string; interval: number; expires_in: number } {\n  if (!v || typeof v !== 'object' || Array.isArray(v)) return false;\n  const o = v as Record<string, unknown>;\n  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';\n}","tryCatchPattern":"try {\n  const pending = await provider.device();\n} catch (e) {\n  if (e instanceof Error && e.message === 'Invalid device code response') {\n    console.error('Device-code endpoint did not return a JSON object. Check the configured GitHub domain/proxy:', e.message);\n    return reconfigureDomainOrProxy();\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["github-copilot","oauth","device-flow","response-shape","network"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}