decolua/9router · error · Error

Failed to get Copilot token: ${error}

Error message

Failed to get Copilot token: ${error}

What it means

GitHubService.getCopilotToken() exchanges the GitHub access token for a short-lived Copilot API token via GET to GITHUB_CONFIG.copilotTokenUrl. On a non-OK response the raw body is wrapped into `Failed to get Copilot token: ${error}` and thrown. Typically this means the authenticated GitHub account does not have an active Copilot subscription or the token lacks the Copilot scope.

Source

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

    }
  }

  /**
   * 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) {
      const error = await response.text();
      throw new Error(`Failed to get Copilot token: ${error}`);
    }

    return await response.json();
  }

  /**
   * Get user info using GitHub access token
   */
  async getUserInfo(accessToken) {
    const response = await fetch(`${GITHUB_CONFIG.userInfoUrl}`, {
      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. Verify the GitHub account has an active Copilot subscription (github.com/settings/copilot).
  2. If using an organization account, confirm Copilot is enabled for your membership in org settings.
  3. Re-authenticate so the token is issued with the scopes the CLI requests.
  4. Check whether GITHUB_CONFIG.copilotTokenUrl / apiVersion still match the current Copilot API; update the library if upstream changed the endpoint.

Example fix

// before
if (!response.ok) {
  const error = await response.text();
  throw new Error(`Failed to get Copilot token: ${error}`);
}
// after
if (!response.ok) {
  const error = await response.text();
  throw new Error(`Failed to get Copilot token (HTTP ${response.status}) — is Copilot enabled for this account? ${error}`);
}
Defensive patterns

Strategy: validation

Validate before calling

function assertCopilotTokenPayload(data) {
  if (!data || typeof data.token !== 'string' || !data.expires_at) {
    throw new Error('Copilot token response missing token/expires_at — is Copilot enabled for this account?');
  }
}

Type guard

function isCopilotTokenResponse(data) {
  return data !== null && typeof data === 'object' && typeof data.token === 'string' && typeof data.expires_at === 'string';
}

Try / catch

try {
  const copilotToken = await service.getCopilotToken(accessToken);
} catch (err) {
  if (err.message.startsWith('Failed to get Copilot token')) {
    console.error('Copilot token request failed — confirm the GitHub account has an active Copilot subscription and org-level Copilot is enabled.');
  }
  throw err;
}

Prevention

When it happens

Trigger: GET to the Copilot token endpoint (api.github.com/copilot_internal/v2/token) returns 403/401/404 — no active Copilot plan for the account, the GitHub token was issued without the required scopes, or the endpoint/API version became unavailable.

Common situations: GitHub account has no Copilot subscription (or trial expired); the organization blocks Copilot for its members; the Copilot API endpoint contract changed (the CLI's hardcoded URL or X-GitHub-Api-Version is stale); rate limiting (403 with rate-limit body).

Related errors


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