decolua/9router · warning · Error

Access denied

Error message

Access denied

What it means

In the GitHub device flow, after the user visits the verification URL, GitHub reports `error: access_denied` if the user explicitly clicked 'Cancel'/'Deny' on the authorization page. pollAccessToken() detects this, fails the spinner with 'Access denied by user.', and throws "Access denied" at github.js:94. The authentication was refused by the human, not by a network or config problem.

Source

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

        spinner.succeed("GitHub authentication successful!");
        return {
          access_token: data.access_token,
          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,
      },

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Re-run the authentication flow and click 'Authorize' instead of 'Cancel' on the GitHub page.
  2. Review the requested scopes (GITHUB_CONFIG.scopes) and confirm you're comfortable granting them before starting.
  3. Verify you are authorizing the correct OAuth app shown on the GitHub confirmation screen.
Defensive patterns

Strategy: try-catch

Type guard

function isAccessDenied(data) {
  return data !== null && typeof data === 'object' && data.error === 'access_denied';
}

Try / catch

try {
  const auth = await service.authenticate();
} catch (err) {
  if (err.message === 'Access denied') {
    console.error('You clicked Deny on the GitHub page. Rerun the flow and click Authorize to continue.');
    return; // no point retrying automatically — the user must consent
  }
  throw err;
}

Prevention

When it happens

Trigger: The poll loop received `{"error":"access_denied"}` from the token endpoint because the user clicked the cancel/deny button on the GitHub device-authorization page.

Common situations: User was suspicious of the app requesting scopes and denied it; user pressed the wrong button on the confirmation page; a shared machine's user declined authorization for someone else's CLI session.

Understand the failure class

Related errors


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