jackwener/OpenCLI · error · CommandExecutionError
Suno feed API failed while polling clips (HTTP ${result.stat
Error message
Suno feed API failed while polling clips (HTTP ${result.status || '?'}) What it means
pollSunoClips throws this CommandExecutionError when /api/feed/v3 returns any non-2xx, non-401/403 HTTP status (e.g. 429, 5xx). The `|| '?'` fallback covers a missing status from a null-ish evaluate result.
Source
Thrown at clis/suno/utils.js:378
const result = unwrapEvaluateResult(await page.evaluate(`(async () => {
const res = await fetch('${STUDIO_API}/api/feed/v3', {
method: 'POST',
headers: ${sunoHeadersJs(deviceId, { 'Content-Type': 'application/json' })},
body: JSON.stringify({ clip_ids: ${idsJson} }),
});
const body = await res.json().catch(() => null);
return { status: res.status, body };
})()`));
if (!result) {
await page.wait(pollSeconds);
continue;
}
if (result.status === 401 || result.status === 403) {
throw new AuthRequiredError(SUNO_DOMAIN, `Suno feed API rejected (HTTP ${result.status}). Re-login.`);
}
if (result.status < 200 || result.status >= 300) {
throw new CommandExecutionError(`Suno feed API failed while polling clips (HTTP ${result.status || '?'})`);
}
if (!result.body || typeof result.body !== 'object' || Array.isArray(result.body)) {
throw new CommandExecutionError('Suno feed API returned malformed JSON while polling clips');
}
const allClips = result.body.clips || [];
if (!Array.isArray(allClips)) {
throw new CommandExecutionError('Suno feed API returned malformed clips payload');
}
const ourClips = allClips.filter(c => targetSet.has(c.id));
const finished = ourClips.filter(c => c.status === 'complete' || c.status === 'error');
if (typeof onProgress === 'function') {
onProgress({ total: clipIds.length, done: finished.length, statuses: ourClips.map(c => `${c.id.slice(0,8)}:${c.status}`) });
}
if (finished.length === clipIds.length) return ourClips;
await page.wait(pollSeconds);View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command after a short wait — most 5xx/429 are transient.
- Increase pollSeconds (e.g. from 5 to 10-15) to reduce request rate.
- Check Suno status/Discord for ongoing outages if 5xx persists.
- Add retry-with-backoff around pollSunoClips for intermittent 429/5xx.
Example fix
// before await pollSunoClips(page, ids, 300, deviceId, 3); // after: slower polling to avoid rate limits await pollSunoClips(page, ids, 300, deviceId, 10);
Defensive patterns
Strategy: retry
Try / catch
try {
const clips = await pollSunoClips(page, ids, timeout, deviceId, 10);
} catch (e) {
if (e instanceof CommandExecutionError && /HTTP \d+/.test(e.message)) {
// transient 429/5xx: back off and retry
await sleep(15000);
return pollSunoClips(page, ids, timeout, deviceId, 15);
}
throw e;
} Prevention
- Use a poll interval of 10s or more to avoid rate limits
- Wrap polling in retry-with-exponential-backoff
- Watch Suno status channels during outages
When it happens
Trigger: The feed polling request gets a 429 rate-limit, 500/502/503 server error, or any other unexpected status outside 200-299 while waiting for clips to finish.
Common situations: Polling too aggressively (small pollSeconds) triggering Suno rate limits; Suno incident/outage causing 5xx responses; network proxy intercepting requests; heavy load during peak generation times.
Related errors
- Flomo API returned HTTP ${resp.status}
- ${label} failed: HTTP ${response.status}
- Sales Navigator lead search API returned an unexpected respo
- lobsters domain returned HTTP ${resp.status}
- HTTP ${probe.httpStatus} from nowcoder profile API
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e4886cd2b0a8f348.
Report an issue: GitHub.