nextlevelbuilder/ui-ux-pro-max-skill · error · GitHubRateLimitError

GitHub API rate limit exceeded. Resets at ${resetDate}.\n${g

Error message

GitHub API rate limit exceeded. Resets at ${resetDate}.\n${getGitHubTokenGuidance()}

What it means

Rate-limit guard in checkRateLimit(): when the GitHub API responds 403 and the x-ratelimit-remaining header is exactly '0', the CLI throws GitHubRateLimitError with the reset time (from x-ratelimit-reset) plus guidance to use a token. Unauthenticated GitHub API requests are limited to 60/hour per IP, so this is the classic anonymous-quota exhaustion on `uipro init`.

Source

Thrown at cli/src/utils/github.ts:38

  }
}

export function getGitHubTokenGuidance(): string {
  return (
    'To increase your GitHub API rate limit, set the UI_PRO_MAX_GITHUB_TOKEN environment variable\n' +
    'to a GitHub Personal Access Token (no scopes needed for public repos).\n' +
    'Create one at: https://github.com/settings/tokens\n' +
    'Example: UI_PRO_MAX_GITHUB_TOKEN=ghp_xxx uipro init\n' +
    'Or pass it directly: uipro init --token ghp_xxx'
  );
}

function checkRateLimit(response: Response): void {
  const remaining = response.headers.get('x-ratelimit-remaining');
  if (response.status === 403 && remaining === '0') {
    const resetTime = response.headers.get('x-ratelimit-reset');
    const resetDate = resetTime ? new Date(parseInt(resetTime) * 1000).toLocaleTimeString() : 'unknown';
    throw new GitHubRateLimitError(
      `GitHub API rate limit exceeded. Resets at ${resetDate}.\n${getGitHubTokenGuidance()}`
    );
  }
  if (response.status === 429) {
    throw new GitHubRateLimitError(
      `GitHub API rate limit exceeded (429 Too Many Requests).\n${getGitHubTokenGuidance()}`
    );
  }
}

function getAuthHeaders(token?: string): Record<string, string> {
  const resolved = (token || process.env['UI_PRO_MAX_GITHUB_TOKEN'] || process.env['GITHUB_TOKEN'])?.trim();
  return resolved ? { 'Authorization': `Bearer ${resolved}` } : {};
}

export async function fetchReleases(token?: string): Promise<Release[]> {
  const url = `${API_BASE}/repos/${REPO_OWNER}/${REPO_NAME}/releases`;

View on GitHub (pinned to a38d04c3d5)

Solutions

  1. Set a token: `UI_PRO_MAX_GITHUB_TOKEN=ghp_xxx uipro init` or `uipro init --token ghp_xxx` (no scopes needed for public repos) — raises the limit to 5,000/hour.
  2. Create the token at https://github.com/settings/tokens if you don't have one.
  3. If you just hit the anonymous limit, wait until the reset time shown in the message and retry.
  4. Cache the downloaded release in CI (or run install once and reuse the target dir) so each job doesn't consume API quota.

Example fix

# before
uipro init
# after
export UI_PRO_MAX_GITHUB_TOKEN=ghp_xxx
uipro init
Defensive patterns

Strategy: fallback

Validate before calling

function hasGitHubToken(): boolean {
  return Boolean(
    (process.env.UI_PRO_MAX_GITHUB_TOKEN || process.env.GITHUB_TOKEN || '').trim()
  );
}
// warn BEFORE calling the API when anonymous
if (!hasGitHubToken()) {
  console.warn('No GitHub token set: anonymous rate limit is 60 req/hour per IP.');
}

Try / catch

try {
  await installFromGitHub(targetDir, aiType, spinner, token);
} catch (e) {
  if (e instanceof GitHubRateLimitError) {
    spinner.fail(e.message); // message already includes reset time + token guidance
    process.exitCode = 1; // or fall back to local assets
  } else throw e;
}

Prevention

When it happens

Trigger: Calling getLatestRelease()/fetchReleases() (i.e. running `uipro init`) without UI_PRO_MAX_GITHUB_TOKEN or GITHUB_TOKEN set, from an IP that has already made ~60 API calls in the past hour — typical in shared CI runners, offices, or VPNs behind one NAT IP.

Common situations: CI pipelines on shared runner pools exhausting the anonymous quota; multiple developers behind the same corporate egress IP; a loop or retry storm in a script calling the installer repeatedly.

Related errors


AI-assisted analysis of nextlevelbuilder/ui-ux-pro-max-skill@a38d04c3d5 (2026-08-14). Data as JSON: /api/errors/537e4a941d431fff. Report an issue: GitHub.