jackwener/OpenCLI · warning · CommandExecutionError
hf spaces returned HTTP 429 (rate limited)
Error message
hf spaces returned HTTP 429 (rate limited)
What it means
The Hugging Face Spaces API responded with HTTP 429 Too Many Requests, meaning the server is rate-limiting this client. The library detects status 429 explicitly and appends guidance: Hugging Face throttles unauthenticated traffic, so wait and retry.
Source
Thrown at clis/hf/spaces.js:65
const url = new URL('https://huggingface.co/api/spaces');
url.searchParams.set('sort', sort);
url.searchParams.set('direction', '-1');
url.searchParams.set('limit', String(limit));
url.searchParams.set('full', 'true');
if (args.search) url.searchParams.set('search', String(args.search));
if (sdk) url.searchParams.set('sdk', sdk);
let resp;
try {
resp = await fetch(url, {
headers: { Accept: 'application/json', 'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)' },
});
}
catch (err) {
throw new CommandExecutionError(`hf spaces request failed: ${err?.message ?? err}`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
'hf spaces returned HTTP 429 (rate limited)',
'Hugging Face throttles unauthenticated traffic; wait a few seconds and retry.',
);
}
if (!resp.ok) {
throw new CommandExecutionError(`hf spaces failed: HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`hf spaces returned malformed JSON: ${err?.message ?? err}`);
}
const list = Array.isArray(data) ? data : [];
if (!list.length) {
throw new EmptyResultError('hf spaces', 'No matching spaces on huggingface.co.');
}View on GitHub (pinned to 49907e53dc)
Solutions
- Wait a few seconds and retry with exponential backoff
- Authenticate requests with an HF token (Authorization: Bearer hf_...) to get a higher rate limit
- Add spacing/jitter between repeated calls or cache results
- Reduce polling frequency in scripts/CI
Example fix
// before: tight loop hammering the API
for (const q of queries) await listSpaces(q);
// after
for (const q of queries) {
await listSpaces(q);
await new Promise((r) => setTimeout(r, 2000));
} Defensive patterns
Strategy: retry
Validate before calling
// throttle your own calls: simple client-side rate limiter
let last = 0;
async function throttled(fn, minGapMs = 2000) {
const wait = last + minGapMs - Date.now();
if (wait > 0) await new Promise(r => setTimeout(r, wait));
last = Date.now();
return fn();
} Try / catch
async function withBackoff(fn, tries = 4) {
for (let i = 0; i < tries; i++) {
try { return await fn(); }
catch (e) {
if (!String(e.message).includes('429') || i === tries - 1) throw e;
await new Promise(r => setTimeout(r, 2 ** i * 1000));
}
}
} Prevention
- Authenticate with an HF token to raise rate limits
- Cache spaces listings instead of re-fetching
- Add delays between repeated calls in scripts/CI
- Use exponential backoff on any 429
When it happens
Trigger: Calling `hf spaces` (GET /api/spaces) too frequently without authentication, so HF's per-IP anonymous rate limit is exceeded and the server returns 429.
Common situations: Scripts or CI pipelines polling the spaces endpoint in a loop without delays; shared CI runner IPs that are already throttled by HF; bursty retries after other failures.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
- coingecko derivatives returned HTTP 429 (rate limited)
- coingecko returned HTTP 429 (rate limited)
- ${label} returned HTTP 429 (rate limited)
- hf paper returned HTTP 429 (rate limited)
- ${label} returned HTTP 429 (rate limited)
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/06a556ece6353c80.
Report an issue: GitHub.