{"record":{"id":"eaeb69d6dcc1b39a","repo":"odysseus-dev/odysseus","slug":"github-device-code-request-failed-e","errorCode":null,"errorMessage":"GitHub device-code request failed: {e}","messagePattern":"GitHub device-code request failed: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":502,"severity":"error","filePath":"routes/copilot_routes.py","lineNumber":113,"sourceCode":"        from routes.model_routes import _invalidate_models_cache\n        _invalidate_models_cache()\n    except Exception:\n        pass\n    return result\n\n\ndef _start_device_flow(request: Request, form) -> DeviceFlowStart:\n    host = copilot.GITHUB_HOST\n    ent = str(form.get(\"enterprise_url\") or \"\").strip()\n    if ent:\n        host = copilot.normalize_domain(ent)\n    try:\n        data = copilot.request_device_code(host)\n    except httpx.HTTPStatusError as e:\n        status = e.response.status_code if e.response is not None else \"unknown\"\n        raise HTTPException(502, f\"GitHub device-code request failed (HTTP {status})\")\n    except Exception as e:\n        raise HTTPException(502, f\"GitHub device-code request failed: {e}\")\n\n    device_code = data.get(\"device_code\")\n    if not device_code:\n        raise HTTPException(502, \"GitHub did not return a device code\")\n\n    # verification_uri_complete embeds the user code, so the browser tab we\n    # open lands the user straight on GitHub's \"Authorize\" screen with the\n    # code pre-filled — one click, no manual code entry.\n    return DeviceFlowStart(\n        pending={\n            \"device_code\": device_code,\n            \"host\": host,\n            \"enterprise_url\": ent,\n            \"owner\": get_current_user(request) or None,\n        },\n        response={\n            \"user_code\": data.get(\"user_code\"),\n            \"verification_uri\": data.get(\"verification_uri\"),","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/copilot_routes.py#L95-L131","documentation":"Raised (HTTP 502) by the Copilot device-flow start helper when copilot.request_device_code(host) fails with any non-HTTPStatusError exception. This is the catch-all branch: network-level failures (DNS failure, connection refused, TLS error, timeout) and unexpected client bugs all land here, with the exception text appended to the message. It means the device-code request never got a usable HTTP response from GitHub / the enterprise host.","triggerScenarios":"Starting Copilot device login while the server has no outbound internet access (air-gapped or proxied environment); DNS for github.com or the enterprise domain fails; a self-signed/enterprise TLS intercept breaks the handshake; the request exceeds the httpx timeout.","commonSituations":"Homelab or corporate network behind a mandatory proxy that is not configured for httpx; typo'd enterprise domain that does not resolve; firewall blocking outbound 443; transient network drop during login start.","solutions":["Read the appended exception text: 'connection refused'/'name or service not known' points to DNS/network, timeouts point to firewall/proxy.","Verify outbound HTTPS from the server: curl -sS https://github.com/login/device/code -o /dev/null -w '%{http_code}'.","Configure the proxy environment (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) the app's httpx client honors if the network requires one.","For enterprise hosts, confirm the domain resolves and serves a valid certificate."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Verify outbound connectivity from the server before offering Copilot login\n// curl -sS -o /dev/null -w '%{http_code}' https://github.com/login/device/code  (expect non-000)","typeGuard":null,"tryCatchPattern":"try { start = await post('/copilot/device/start', form); } catch (e) { if (e.status === 502) { const cause = e.message.split(': ').pop(); if (/timed? ?out|connect|resolve/i.test(cause)) showBanner('Server cannot reach GitHub — check proxy/firewall.'); } throw e; }","preventionTips":["Configure HTTP_PROXY/HTTPS_PROXY for environments that require an egress proxy.","Smoke-test outbound HTTPS from the server host as part of deployment checks."],"tags":["copilot","oauth","device-flow","network","proxy"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}