jackwener/OpenCLI · error · CommandExecutionError
Suno feed API returned malformed clips payload
Error message
Suno feed API returned malformed clips payload
What it means
Even when the feed body is a valid JSON object, pollSunoClips requires body.clips to be an array. If clips is missing or a non-array (object, string, etc.), this CommandExecutionError is thrown before filtering target clip ids.
Source
Thrown at clis/suno/utils.js:386
})()`));
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);
}
throw new TimeoutError(`Suno generation did not complete within ${timeoutSeconds}s. Try --timeout <higher>.`);
}
// ─────────────────────────────────────────────────────────────────────────────
// Asset download.
// ─────────────────────────────────────────────────────────────────────────────View on GitHub (pinned to 49907e53dc)
Solutions
- Update the opencli suno CLI to match the current Suno feed schema.
- Log result.body keys to discover where the clips array moved (e.g. body.data.clips).
- Retry in case a transient backend error object was returned with 200.
- Pin/report the issue if Suno is mid-migration and behavior is inconsistent.
Example fix
// before
const allClips = result.body.clips || [];
if (!Array.isArray(allClips)) throw new CommandExecutionError('Suno feed API returned malformed clips payload');
// after: tolerate nested envelope
const raw = result.body.clips ?? result.body.data?.clips ?? [];
const allClips = Array.isArray(raw) ? raw : []; Defensive patterns
Strategy: type-guard
Validate before calling
// validate clips is an array before filtering
const raw = body?.clips ?? body?.data?.clips;
if (!Array.isArray(raw)) throw new Error('unexpected feed schema: ' + Object.keys(body || {}).join(',')); Type guard
function hasClipsArray(body) {
return Array.isArray(body?.clips) || Array.isArray(body?.data?.clips);
} Try / catch
try {
const clips = await pollSunoClips(page, ids, timeout, deviceId);
} catch (e) {
if (e instanceof CommandExecutionError && /malformed clips payload/.test(e.message)) {
// schema drift: update CLI or fall back to manual feed inspection
}
throw e;
} Prevention
- Keep the Suno CLI updated against feed schema changes
- Log body keys when the shape looks wrong
- Pin a known-good CLI version in CI
When it happens
Trigger: The feed endpoint returns 2xx JSON whose `clips` field is absent, null, or not an array — a partial API schema change or an error object returned with 200 status.
Common situations: Suno rolls out a new feed envelope (e.g. clips nested under data); backend error payloads returned with HTTP 200; region-specific API variants with different shapes.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Suno generate returned malformed JSON payload.
- Submission accepted but Suno returned no clip ids. Raw: ${JS
- Cannot resolve aid for bvid: ${bvid}
- Bilibili reply add API did not return rpid for the posted co
- eastmoney convertible returned a malformed response envelope
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8794cacb29a6e090.
Report an issue: GitHub.