{"record":{"id":"2d762d989fd45c22","repo":"headroomlabs-ai/headroom","slug":"github-device-authorization-failed-description","errorCode":null,"errorMessage":"GitHub device authorization failed: {description}","messagePattern":"GitHub device authorization failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"headroom/copilot_auth.py","lineNumber":598,"sourceCode":"            raise RuntimeError(\"GitHub device authorization returned an invalid response.\")\n\n        access_token = payload.get(\"access_token\")\n        if isinstance(access_token, str) and access_token.strip():\n            return access_token.strip()\n\n        error = str(payload.get(\"error\") or \"\").strip()\n        if error == \"authorization_pending\":\n            time.sleep(poll_interval)\n            continue\n        if error == \"slow_down\":\n            poll_interval += 5\n            time.sleep(poll_interval)\n            continue\n        if error == \"expired_token\":\n            raise RuntimeError(\"GitHub device authorization expired.\")\n        if error:\n            description = str(payload.get(\"error_description\") or error).strip()\n            raise RuntimeError(f\"GitHub device authorization failed: {description}\")\n\n        time.sleep(poll_interval)\n\n    raise RuntimeError(\"GitHub device authorization expired.\")\n\n\ndef _extract_oauth_token(entry: dict[str, Any]) -> str | None:\n    if _entry_expired(entry):\n        return None\n\n    for key in _OAUTH_TOKEN_KEYS:\n        value = entry.get(key)\n        if isinstance(value, str) and value.strip():\n            return value.strip()\n\n    for value in entry.values():\n        if isinstance(value, dict):\n            nested = _extract_oauth_token(value)","sourceCodeStart":580,"sourceCodeEnd":616,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/copilot_auth.py#L580-L616","documentation":"Generic failure branch of the device-flow token poll: GitHub returned a JSON dict with a non-empty 'error' that is neither authorization_pending, slow_down, nor expired_token. The error_description (falling back to the error code) is embedded in the RuntimeError. Typical underlying codes: incorrect_client_credentials, incorrect_device_code, access_denied (user clicked deny), unsupported_grant_type.","triggerScenarios":"The user denies the consent page (access_denied); the client_id sent to the device_code endpoint is invalid or revoked (incorrect_client_credentials); the device_code is malformed/reused from a previous flow; device flow disabled for the GitHub App.","commonSituations":"Users pressing 'Cancel' on the GitHub authorize page; hardcoded/rotated client IDs in forks of the tool; GHE admins disabling OAuth device flow; retrying a device_code from an old run after it was consumed.","solutions":["Read the embedded description: access_denied means the user denied consent — re-run and approve; incorrect_client_credentials means the client_id is wrong — check the configured GitHub App / client ID","Start a brand-new device flow (fresh device_code) rather than reusing one","On GitHub Enterprise, have an admin confirm the OAuth App permits the device flow grant","Handle this as a non-retryable auth failure — do not loop, surface the message to the user"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    token = poll_copilot_device_authorization(device_code, ...)\nexcept RuntimeError as e:\n    msg = str(e)\n    if \"access_denied\" in msg:\n        raise SystemExit(\"User denied Copilot authorization — re-run and approve\") from e\n    if \"incorrect_client_credentials\" in msg:\n        raise SystemExit(\"Client ID invalid — check the GitHub App configuration\") from e\n    raise  # other errors: do not retry blindly","preventionTips":["Treat embedded error_description as terminal (deny/bad credentials) — never auto-retry the same device_code","Keep the client_id used for device_code and token polls identical","Alert users that clicking Cancel on GitHub's consent page produces this failure"],"tags":["auth","oauth","github","device-flow","access-denied"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}