jackwener/OpenCLI · error · CommandExecutionError
Suno feed lookup returned malformed clips payload
Error message
Suno feed lookup returned malformed clips payload
What it means
`opencli suno download` fetches the user's Suno feed via an in-page API call and expects `feedRes.clips` to be an array so it can find the requested clip. This CommandExecutionError is thrown when the feed endpoint responds ok but the `clips` field is missing, null, or not an array — i.e. Suno's payload shape changed or the response is not a feed payload. It is a defensive guard against silently calling `.find()` on undefined.
Source
Thrown at clis/suno/download.js:108
headers: {
'Authorization': 'Bearer ' + (await window.Clerk.session.getToken()),
'browser-token': browserToken,
'device-id': ${JSON.stringify(deviceId)},
'Content-Type': 'application/json',
},
body: JSON.stringify({ clip_ids: ['${clipId}'] }),
});
if (!res.ok) return { ok: false, error: 'HTTP ' + res.status };
const payload = await res.json().catch(() => null);
if (!payload || !Array.isArray(payload.clips)) return { ok: false, error: 'malformed clips payload' };
return { ok: true, clips: payload.clips };
})()`));
if (!feedRes?.ok) {
throw new CommandExecutionError(`Suno feed lookup failed: ${feedRes?.error || 'unknown'}`);
}
if (!Array.isArray(feedRes.clips)) {
throw new CommandExecutionError('Suno feed lookup returned malformed clips payload');
}
const clip = feedRes.clips.find(c => c.id === clipId);
if (!clip) {
throw new EmptyResultError('suno download', `Clip ${clipId} not found in your account. Confirm at ${SUNO_URL}/song/${clipId}.`);
}
if (clip.status !== 'complete') {
throw new CommandExecutionError(`Clip ${clipId} status is "${clip.status}" — not complete yet. Retry once generation finishes.`);
}
const result = await downloadSunoClip(page, clip, outputDir, formats, deviceId);
if (!result.written.some(w => w.ok)) {
throw new CommandExecutionError(`Suno download wrote no files for clip ${clipId}`);
}
const link = `${SUNO_URL}/song/${clip.id}`;
const writtenSummary = result.written
.map(w => w.ok ? `${w.format}:${displayPath(w.file)}` : `${w.format}:✗(${w.reason})`)
.join(' | ');
const skippedSummary = skippedPaid.lengthView on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; transient/degraded feed responses often resolve on retry.
- Refresh the Suno session: open https://suno.com in Chrome, confirm you are logged in, then retry the command.
- Check for an updated opencli version that tracks the current Suno feed API schema (npm update / reinstall @jackwener/opencli).
- Inspect the raw feed response manually (browser devtools on suno.com feed endpoint) to confirm the schema and file an issue if it diverged.
Defensive patterns
Strategy: type-guard
Validate before calling
// after invoking the feed lookup, before using clips
if (!feedRes?.ok) throw new Error('feed lookup failed');
if (!Array.isArray(feedRes.clips)) throw new Error('malformed clips payload'); Type guard
function hasClips(res) {
return res != null && typeof res === 'object' && Array.isArray(res.clips);
} Try / catch
try {
await run('opencli suno download <id>');
} catch (err) {
if (String(err.message).includes('malformed clips payload')) {
// retry once, then refresh session / report schema drift
} else throw err;
} Prevention
- Keep the CLI updated so it tracks Suno's current feed response schema.
- Retry transiently before assuming a hard failure.
- Re-login to suno.com in the driven Chrome profile when payloads look degraded.
When it happens
Trigger: Running `opencli suno download <clip-id>` when the Suno feed API returns HTTP ok but a body where `clips` is absent/not an array — e.g. Suno changed the feed response schema, an auth/degraded response returns a JSON object without `clips`, or the page-eval bridge unwraps an unexpected object.
Common situations: Suno frontend/API version drift (site updated response shape), expired or partially-valid session cookies yielding a soft-error JSON body with HTTP 200, rate-limited or region-blocked responses that still return ok, or proxy/CDN interstitials returning non-feed JSON.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Bilibili creator comparison API returned a malformed envelop
- ${label} returned a malformed API envelope
- nuget package registration leaf ${pageUrl} did not include a
- Suno whoami failed: ${probe.detail}
- Suno feed lookup failed: ${feedRes?.error || 'unknown'}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9304a7f25c0ead33.
Report an issue: GitHub.