{"record":{"id":"29e975a25a5ff829","repo":"upstash/context7","slug":"err-error-description-err-error-device-token-poll-failed","errorCode":null,"errorMessage":"${err.error_description || err.error || \"Device token poll failed\"}","messagePattern":"\\$\\{err\\.error_description \\|\\| err\\.error \\|\\| \"Device token poll failed\"\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/auth.ts","lineNumber":312,"sourceCode":"    const err = (await response.json().catch(() => ({}))) as TokenErrorResponse;\n    return {\n      status: \"transient\",\n      errorMessage: err.error_description || err.error || `HTTP ${response.status}`,\n    };\n  }\n\n  const err = (await response.json().catch(() => ({}))) as TokenErrorResponse;\n  switch (err.error) {\n    case \"authorization_pending\":\n      return { status: \"pending\" };\n    case \"slow_down\":\n      return { status: \"slow_down\" };\n    case \"access_denied\":\n      return { status: \"denied\" };\n    case \"expired_token\":\n      return { status: \"expired\" };\n    default:\n      throw new Error(err.error_description || err.error || \"Device token poll failed\");\n  }\n}\n","sourceCodeStart":294,"sourceCodeEnd":315,"githubUrl":"https://github.com/upstash/context7/blob/4416fb855b8f752be735e34f943b5d0762701aad/packages/cli/src/utils/auth.ts#L294-L315","documentation":"Thrown by pollDeviceToken when the RFC 8628 device-flow token endpoint returns a terminal error code other than the handled authorization_pending, slow_down, access_denied, and expired_token cases. The message is the server-provided error_description or error code, defaulting to 'Device token poll failed'. Terminal OAuth codes like invalid_grant, unsupported_grant_type, or invalid_client land here.","triggerScenarios":"Polling the device token endpoint and receiving an error body whose `error` field is not one of the four handled values — e.g. invalid_client (misconfigured client ID), invalid_grant (device code rejected), unsupported_grant_type, or a malformed body with an unexpected error string.","commonSituations":"Client credentials misconfigured on the provider, device code already consumed by another poller, provider protocol deviations, or clock/tenant issues causing the server to reject the grant outright.","solutions":["Read the message for the server's error code and fix the underlying cause (e.g. invalid_client → fix client ID configuration)","Restart the device authorization flow from the beginning to obtain a fresh device code","Verify the OAuth client is configured to allow the device_code grant type on the provider","Check for multiple concurrent pollers — a device code can only be redeemed once"],"exampleFix":"// before: treating every error as retryable\nwhile (true) { try { return await poll(); } catch { await sleep(5_000); } }\n// after: fail fast on terminal errors (thrown) vs handled pending states\nconst result = await pollDeviceToken(deviceCode);\nif (result.status === \"pending\") await sleep(interval);","handlingStrategy":"try-catch","validationCode":"// ensure device grant is supported before starting the flow\nconst meta = await fetchDiscoveryMetadata(issuer);\nif (!meta.grant_types_supported?.includes(\"urn:ietf:params:oauth:grant-type:device_code\")) {\n  throw new Error(\"Provider does not support the device flow\");\n}","typeGuard":"function isTerminalDeviceError(code: string): boolean {\n  return ![\"authorization_pending\", \"slow_down\", \"access_denied\", \"expired_token\"].includes(code);\n}","tryCatchPattern":"try {\n  const tokens = await pollDeviceToken(deviceCode);\n} catch (e) {\n  console.error(`Device flow failed: ${e.message} — restart the login flow`);\n  await restartDeviceAuthorization();\n}","preventionTips":["Verify the OAuth client has the device_code grant enabled","Do not run multiple pollers for the same device code","Respect the server's interval (and slow_down backoff) while polling"],"tags":["oauth","device-flow","polling","cli"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"4416fb855b8f752be735e34f943b5d0762701aad","analyzedAt":"2026-09-16T20:28:07.148Z","contentChangedAt":"2026-09-16T20:28:07.148Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}