odysseus-dev/odysseus · error · HTTPException

GitHub device-code request failed: {e}

Error message

GitHub device-code request failed: {e}

What it means

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.

Source

Thrown at routes/copilot_routes.py:113

        from routes.model_routes import _invalidate_models_cache
        _invalidate_models_cache()
    except Exception:
        pass
    return result


def _start_device_flow(request: Request, form) -> DeviceFlowStart:
    host = copilot.GITHUB_HOST
    ent = str(form.get("enterprise_url") or "").strip()
    if ent:
        host = copilot.normalize_domain(ent)
    try:
        data = copilot.request_device_code(host)
    except httpx.HTTPStatusError as e:
        status = e.response.status_code if e.response is not None else "unknown"
        raise HTTPException(502, f"GitHub device-code request failed (HTTP {status})")
    except Exception as e:
        raise HTTPException(502, f"GitHub device-code request failed: {e}")

    device_code = data.get("device_code")
    if not device_code:
        raise HTTPException(502, "GitHub did not return a device code")

    # verification_uri_complete embeds the user code, so the browser tab we
    # open lands the user straight on GitHub's "Authorize" screen with the
    # code pre-filled — one click, no manual code entry.
    return DeviceFlowStart(
        pending={
            "device_code": device_code,
            "host": host,
            "enterprise_url": ent,
            "owner": get_current_user(request) or None,
        },
        response={
            "user_code": data.get("user_code"),
            "verification_uri": data.get("verification_uri"),

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Read the appended exception text: 'connection refused'/'name or service not known' points to DNS/network, timeouts point to firewall/proxy.
  2. Verify outbound HTTPS from the server: curl -sS https://github.com/login/device/code -o /dev/null -w '%{http_code}'.
  3. Configure the proxy environment (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) the app's httpx client honors if the network requires one.
  4. For enterprise hosts, confirm the domain resolves and serves a valid certificate.
Defensive patterns

Strategy: retry

Validate before calling

// Verify outbound connectivity from the server before offering Copilot login
// curl -sS -o /dev/null -w '%{http_code}' https://github.com/login/device/code  (expect non-000)

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/eaeb69d6dcc1b39a. Report an issue: GitHub.