jackwener/OpenCLI · error · CommandExecutionError
All Suno clips failed (${errors}). Open ${SUNO_URL}/song/${c
Error message
All Suno clips failed (${errors}). Open ${SUNO_URL}/song/${clipIds[0]} to inspect. What it means
After polling, if none of the generated clips reached status 'complete', the CLI throws listing each clip's short id and terminal status, with a link to the first clip for manual inspection.
Source
Thrown at clis/suno/generate.js:184
deviceId,
});
if (!Array.isArray(submission.clips)) {
throw new CommandExecutionError('Suno generation returned malformed clips payload.');
}
const clipIds = submission.clips.map(c => c?.id);
if (clipIds.some(id => !id)) {
throw new CommandExecutionError('Suno generation returned malformed clip identity.');
}
if (!clipIds.length) {
throw new CommandExecutionError('Suno accepted the request but returned no clip ids.');
}
const clips = await pollSunoClips(page, clipIds, timeout, deviceId);
const completed = clips.filter(c => c.status === 'complete');
if (!completed.length) {
const errors = clips.map(c => `${c.id.slice(0, 8)}:${c.status}`).join(', ');
throw new CommandExecutionError(`All Suno clips failed (${errors}). Open ${SUNO_URL}/song/${clipIds[0]} to inspect.`);
}
const rows = [];
for (const clip of clips) {
const link = `${SUNO_URL}/song/${clip.id}`;
if (clip.status !== 'complete') {
rows.push({
status: `❌ ${clip.status}`,
clip: clip.id.slice(0, 8),
title: clip.title || '(untitled)',
files: '-',
link: `🔗 ${link}`,
});
continue;
}
if (skipDownload) {
rows.push({
status: '🎵 generated',View on GitHub (pinned to 49907e53dc)
Solutions
- Open the song URL from the message (https://suno.com/song/<clipId>) to see Suno's own failure reason.
- Read the per-clip statuses in the error (e.g. abc12345:error) — 'error' usually means moderation rejection, timeout means backlog.
- Retry with a longer --timeout if clips were still queued.
- Rephrase prompt/lyrics or switch --model and regenerate.
Example fix
// before: single 60s wait, gives up on slow queue const clips = await pollSunoClips(page, clipIds, 60, deviceId); // after: allow more time for Suno backlog const clips = await pollSunoClips(page, clipIds, 300, deviceId);
Defensive patterns
Strategy: retry
Validate before calling
// Prefer generous timeouts up front; check account eligibility for the chosen model:
await opencli('suno', 'generate', prompt, '--timeout', '300'); // default 300s, raise for backlogs Type guard
function anyCompleted(clips) { return Array.isArray(clips) && clips.some(c => c?.status === 'complete'); } Try / catch
try {
const rows = await opencli('suno', 'generate', prompt);
} catch (e) {
const m = /All Suno clips failed \((.+)\)/.exec(e.message);
if (m) {
const statuses = m[1];
if (/timeout/i.test(statuses)) await retryWithLongerTimeout();
else if (/error|failed/i.test(statuses)) reportModerationOrContentIssue(statuses);
} else throw e;
} Prevention
- Use --timeout 300+ during Suno peak hours.
- Avoid lyric content that commonly trips moderation.
- Check clip status in the error string to pick retry vs rephrase.
- Open the song URL from the message for Suno's own failure detail.
When it happens
Trigger: `pollSunoClips()` returns clips where no `c.status === 'complete'` — all clips ended 'error', 'failed', or timed out in a non-complete state within --timeout.
Common situations: Content-moderation failure on the prompt/lyrics, Suno compute backlog causing timeouts, unsupported model tag, or lyrics with malformed metatags.
Related errors
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- ${config.site} login
- Timeout waiting for Antigravity reply after ${timeout / 1000
- FETCH_ERROR
- archive wayback request failed: ${error?.message || error}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f769c35e164b462f.
Report an issue: GitHub.