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
- 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.
- Create the token at https://github.com/settings/tokens if you don't have one.
- If you just hit the anonymous limit, wait until the reset time shown in the message and retry.
- 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
- Always export UI_PRO_MAX_GITHUB_TOKEN in CI before running uipro init.
- Cache the downloaded release (keyed by tag) so repeat installs make zero API calls.
- Never retry immediately on 403/remaining=0 — wait for the reset time shown in the message.
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
- Failed to fetch releases: ${response.status} ${response.stat
- No ZIP asset found in latest release
- Failed to fetch latest release: ${response.status} ${respons
- Failed to download: ${response.status} ${response.statusText
- Failed to extract zip: ${error}
AI-assisted analysis of nextlevelbuilder/ui-ux-pro-max-skill@a38d04c3d5 (2026-08-14).
Data as JSON: /api/errors/537e4a941d431fff.
Report an issue: GitHub.