jackwener/OpenCLI · error · CommandExecutionError
DuckDuckGo suggest returned HTTP ${resp.status}
Error message
DuckDuckGo suggest returned HTTP ${resp.status} What it means
After the fetch resolves, the suggest command checks resp.ok. Any non-2xx HTTP status from the DuckDuckGo autocomplete endpoint (429 rate limit, 403 blocked, 5xx server error) produces this CommandExecutionError with the status code embedded. Unlike error 1317, the request reached the server but was rejected.
Source
Thrown at clis/duckduckgo/suggest.js:29
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'keyword', positional: true, required: true, help: 'Search query prefix' },
{ name: 'limit', type: 'int', default: 8, help: 'Max number of suggestions' },
],
columns: ['phrase'],
func: async (kwargs) => {
const limit = requireBoundedInteger(kwargs.limit, 8, 1, 20, '--limit');
const keyword = encodeURIComponent(requireSearchQuery(kwargs.keyword));
const url = `https://duckduckgo.com/ac/?q=${keyword}&type=list`;
let resp;
try {
resp = await fetch(url);
} catch (err) {
throw new CommandExecutionError(`DuckDuckGo suggest request failed: ${err instanceof Error ? err.message : String(err)}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`DuckDuckGo suggest returned HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
} catch (err) {
throw new CommandExecutionError(`DuckDuckGo suggest returned malformed JSON: ${err?.message ?? err}`);
}
const phrases = Array.isArray(data) && data.length > 1 && Array.isArray(data[1]) ? data[1] : [];
return phrases
.filter((phrase) => typeof phrase === 'string' && phrase.trim())
.slice(0, limit)
.map(function(p) { return { phrase: p }; });
},
});
export const __test__ = { command };
View on GitHub (pinned to 49907e53dc)
Solutions
- Read the embedded HTTP status in the message to identify the cause
- Add delays/backoff between suggest requests; back off aggressively on 429
- Retry later on 5xx; check DuckDuckGo status if persistent
- Use a different network/IP if 403-blocked (avoid datacenter IPs)
- Catch CommandExecutionError and degrade gracefully (return empty suggestions)
Example fix
// before
for (const k of keywords) suggestions[k] = await ddgSuggest({ keyword: k });
// after
for (const k of keywords) {
await sleep(1000); // avoid 429
try { suggestions[k] = await ddgSuggest({ keyword: k }); }
catch (e) { suggestions[k] = []; }
} Defensive patterns
Strategy: retry
Validate before calling
// throttle yourself: at most 1 suggest call per second
let last = 0;
async function throttledSuggest(kw) {
const wait = Math.max(0, 1000 - (Date.now() - last));
await sleep(wait); last = Date.now();
return ddgSuggest({ keyword: kw });
} Try / catch
try {
return await ddgSuggest({ keyword });
} catch (err) {
const m = /HTTP (\d+)/.exec(err?.message ?? '');
const status = m ? Number(m[1]) : 0;
if (status === 429 || status >= 500) {
await sleep(status === 429 ? 10000 : 2000);
return ddgSuggest({ keyword });
}
if (status === 403 || status === 404) return []; // blocked/not offered
throw err;
} Prevention
- Rate-limit suggest requests; back off on 429
- Avoid datacenter IPs that get 403-blocked
- Monitor for DuckDuckGo outages before blaming your code
- Cache suggestion results to reduce call volume
When it happens
Trigger: DuckDuckGo returns 403 (bot/anti-abuse block), 429 (rate limited from rapid repeated calls), 5xx (server-side incident), or a captive portal's 30x/200 HTML handled as non-ok.
Common situations: Looping over many keywords too quickly and hitting rate limits; running from datacenter/CI IPs that DuckDuckGo throttles; DuckDuckGo outage; blocked region or VPN IP.
Related errors
- Xiaoyuzhou transcript download failed with HTTP ${response.s
- archive snapshots failed: HTTP ${resp.status}
- coingecko returned HTTP 429 (rate limited)
- hf paper returned HTTP 429 (rate limited)
- Instagram private publish ${stage} failed: ${response.status
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d1af7f178a25b3e8.
Report an issue: GitHub.