decolua/9router · error · Error

`Device code request failed: ${error}`

Error message

`Device code request failed: ${error}`

What it means

GitHub device-flow step 1: the POST to GitHub's device/code endpoint (client_id + scopes) returned a non-2xx status, and the body text is thrown. Without a device_code the polling loop can never start, so GitHub login aborts immediately.

Source

Thrown at src/lib/oauth/providers/github.js:21

const github = {
  config: GITHUB_CONFIG,
  flowType: "device_code",
  requestDeviceCode: async (config) => {
    const response = await fetch(config.deviceCodeUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        Accept: "application/json",
      },
      body: new URLSearchParams({
        client_id: config.clientId,
        scope: config.scopes,
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(`Device code request failed: ${error}`);
    }

    return await response.json();
  },
  pollToken: async (config, deviceCode) => {
    const response = await fetch(config.tokenUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        Accept: "application/json",
      },
      body: new URLSearchParams({
        client_id: config.clientId,
        device_code: deviceCode,
        grant_type: "urn:ietf:params:oauth:grant-type:device_code",
      }),
    });

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Read the body: 422 usually means bad client_id or scope format; fix config accordingly.
  2. Verify the GitHub OAuth app's client_id is valid and the app is not suspended.
  3. Test reachability: curl -X POST https://github.com/login/device/code.
  4. Check GitHub status / retry with backoff if the body shows 5xx.

Example fix

// before
if (!response.ok) {
  const error = await response.text();
  throw new Error(`Device code request failed: ${error}`);
}
// after
if (!response.ok) {
  const error = await response.text();
  throw new Error(`Device code request failed (HTTP ${response.status}): ${error}`);
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate inputs GitHub requires before the device-code request
if (!config.clientId) throw new Error("GitHub OAuth client_id missing");
if (!/^([a-z0-9:-]+,?)+$/i.test(config.scopes || "")) throw new Error("GitHub scopes malformed — use comma/space separated scope names");

Type guard

function hasValidDeviceCodeResponse(v) {
  return !!v && typeof v === "object" &&
    typeof v.device_code === "string" &&
    typeof v.user_code === "string" &&
    typeof v.verification_uri === "string";
}

Try / catch

try {
  const dc = await githubProvider.startDeviceFlow();
} catch (err) {
  if (String(err.message).includes("Device code request failed")) {
    if (responseWas(422)) console.error("Bad client_id or scope format for GitHub");
    else await retryWithBackoff(() => githubProvider.startDeviceFlow(), { retries: 2 });
  } else throw err;
}

Prevention

When it happens

Trigger: Calling startDeviceFlow for github when the https://github.com/login/device/code endpoint replies !response.ok — 404 (endpoint moved/blocked), 422 bad client_id or malformed scope string, 403 via proxy, or 5xx GitHub incident.

Common situations: Wrong/revoked GitHub OAuth app client_id; scopes joined incorrectly (spaces vs commas causing 422); corporate proxy or offline machine; GitHub status incident; DNS blocking github.com.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/95245e3eee49b000. Report an issue: GitHub.