{"record":{"id":"ce5f8e65fcb59eae","repo":"decolua/9router","slug":"data-error-description-data-error","errorCode":null,"errorMessage":"${data.error_description || data.error}","messagePattern":"\\$\\{data\\.error_description \\|\\| data\\.error\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/github.js","lineNumber":97,"sourceCode":"          token_type: data.token_type,\n          scope: data.scope,\n        };\n      } else if (data.error === \"authorization_pending\") {\n        // Continue polling\n        continue;\n      } else if (data.error === \"slow_down\") {\n        // Increase polling interval\n        interval += 5000;\n        continue;\n      } else if (data.error === \"expired_token\") {\n        spinner.fail(\"Device code expired. Please try again.\");\n        throw new Error(\"Device code expired\");\n      } else if (data.error === \"access_denied\") {\n        spinner.fail(\"Access denied by user.\");\n        throw new Error(\"Access denied\");\n      } else {\n        spinner.fail(\"Failed to get access token.\");\n        throw new Error(data.error_description || data.error);\n      }\n    }\n  }\n\n  /**\n   * Get Copilot token using GitHub access token\n   */\n  async getCopilotToken(accessToken) {\n    const response = await fetch(`${GITHUB_CONFIG.copilotTokenUrl}`, {\n      headers: {\n        Authorization: `Bearer ${accessToken}`, // GitHub API typically uses Bearer\n        Accept: \"application/json\",\n        \"X-GitHub-Api-Version\": GITHUB_CONFIG.apiVersion,\n        \"User-Agent\": GITHUB_CONFIG.userAgent,\n      },\n    });\n\n    if (!response.ok) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/github.js#L79-L115","documentation":"The final catch-all branch of the pollAccessToken() poll loop: GitHub returned an error code that is not authorization_pending, slow_down, expired_token, or access_denied. The library throws the raw `error_description` or `error` from GitHub's JSON response. Known GitHub device-flow errors landing here include `unsupported_grant_type`, `incorrect_client_credentials`, `incorrect_device_code`, and `device_flow_disabled`.","triggerScenarios":"pollAccessToken() received an unrecognized OAuth error payload from https://github.com/login/oauth/access_token — e.g. a wrong or reused device_code (`incorrect_device_code`), an invalid client_id (`incorrect_client_credentials`), or a malformed grant request (`unsupported_grant_type`).","commonSituations":"The device_code was reused from a previous expired attempt; GITHUB_CONFIG.clientId is wrong or the OAuth app has device flow disabled; a proxy mutated the response so `data.error` holds something unexpected.","solutions":["Restart the full authenticate() flow so a fresh device_code is issued instead of reusing an old one.","Check the thrown message: `incorrect_client_credentials`/`device_flow_disabled` means GITHUB_CONFIG.clientId or the OAuth app's device-flow setting is wrong — fix the config or app settings.","Confirm no proxy is rewriting responses from github.com (compare with curl).","If the message is empty, patch to log the full `data` payload for diagnosis."],"exampleFix":"// before\nthrow new Error(data.error_description || data.error);\n// after\nthrow new Error(`Device flow error: ${data.error_description || data.error} (raw: ${JSON.stringify(data)})`);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isKnownPollError(data) {\n  return ['authorization_pending','slow_down','expired_token','access_denied'].includes(data?.error);\n}","tryCatchPattern":"try {\n  const auth = await service.authenticate();\n} catch (err) {\n  if (err.message === 'Access denied' || err.message === 'Device code expired') throw err; // known, actionable\n  if (err.message.startsWith('GitHub authentication failed')) {\n    console.error(`Unrecognized device-flow error: ${err.message}. Restart the flow with a fresh device code; if it persists, check client_id / device-flow app settings.`);\n  }\n  throw err;\n}","preventionTips":["Always issue a fresh device_code per attempt — reusing codes produces incorrect_device_code.","Validate the OAuth app has device flow enabled and the client_id is correct before shipping config.","Log the full poll response payload when an unknown error appears so the GitHub error code is captured.","Wrap the outer wrapper to preserve `{ cause }` so the original poll error isn't lost."],"tags":["oauth","github","device-flow","configuration"],"backgroundTag":"oauth-device-flow-error","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}