decolua/9router · error · Error

${data.error_description || data.error}

Error message

${data.error_description || data.error}

What it means

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`.

Source

Thrown at src/lib/oauth/services/github.js:97

          token_type: data.token_type,
          scope: data.scope,
        };
      } else if (data.error === "authorization_pending") {
        // Continue polling
        continue;
      } else if (data.error === "slow_down") {
        // Increase polling interval
        interval += 5000;
        continue;
      } else if (data.error === "expired_token") {
        spinner.fail("Device code expired. Please try again.");
        throw new Error("Device code expired");
      } else if (data.error === "access_denied") {
        spinner.fail("Access denied by user.");
        throw new Error("Access denied");
      } else {
        spinner.fail("Failed to get access token.");
        throw new Error(data.error_description || data.error);
      }
    }
  }

  /**
   * Get Copilot token using GitHub access token
   */
  async getCopilotToken(accessToken) {
    const response = await fetch(`${GITHUB_CONFIG.copilotTokenUrl}`, {
      headers: {
        Authorization: `Bearer ${accessToken}`, // GitHub API typically uses Bearer
        Accept: "application/json",
        "X-GitHub-Api-Version": GITHUB_CONFIG.apiVersion,
        "User-Agent": GITHUB_CONFIG.userAgent,
      },
    });

    if (!response.ok) {

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Restart the full authenticate() flow so a fresh device_code is issued instead of reusing an old one.
  2. 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.
  3. Confirm no proxy is rewriting responses from github.com (compare with curl).
  4. If the message is empty, patch to log the full `data` payload for diagnosis.

Example fix

// before
throw new Error(data.error_description || data.error);
// after
throw new Error(`Device flow error: ${data.error_description || data.error} (raw: ${JSON.stringify(data)})`);
Defensive patterns

Strategy: try-catch

Type guard

function isKnownPollError(data) {
  return ['authorization_pending','slow_down','expired_token','access_denied'].includes(data?.error);
}

Try / catch

try {
  const auth = await service.authenticate();
} catch (err) {
  if (err.message === 'Access denied' || err.message === 'Device code expired') throw err; // known, actionable
  if (err.message.startsWith('GitHub authentication failed')) {
    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.`);
  }
  throw err;
}

Prevention

When it happens

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

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

Related errors


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