jackwener/OpenCLI · error · CommandExecutionError
Suno generate returned malformed JSON payload.
Error message
Suno generate returned malformed JSON payload.
What it means
submitSunoGeneration POSTs to Suno's /api/generate/v2-web/ endpoint inside the browser page. If the HTTP status is 2xx but the response body could not be parsed into a JSON object (null, non-object, or array), this CommandExecutionError is thrown. It guards the contract that the response is an object containing a clips array.
Source
Thrown at clis/suno/utils.js:341
let parsed = null;
try { parsed = JSON.parse(text); } catch {}
return { status: res.status, ok: res.ok, body: parsed, raw: parsed ? null : text.slice(0, 600) };
})()`));
if (!result || !result.ok) {
const status = result?.status || 'unknown';
const detail = result?.body?.detail || result?.raw || JSON.stringify(result?.body || {}).slice(0, 500);
if (status === 401 || status === 403) {
throw new AuthRequiredError(SUNO_DOMAIN, `Suno API rejected request (HTTP ${status}). Re-login on suno.com.`);
}
if (status === 402) {
throw new CommandExecutionError(`Suno API: insufficient credits (HTTP 402). ${detail}`);
}
throw new CommandExecutionError(`Suno generate failed (HTTP ${status}): ${detail}`);
}
if (!result.body || typeof result.body !== 'object' || Array.isArray(result.body)) {
throw new CommandExecutionError('Suno generate returned malformed JSON payload.');
}
const clips = result.body?.clips || [];
if (!clips.length) {
throw new EmptyResultError('suno generate', `Submission accepted but Suno returned no clip ids. Raw: ${JSON.stringify(result.body).slice(0, 300)}`);
}
return result.body;
}
// ─────────────────────────────────────────────────────────────────────────────
// Poll /api/feed/v3 (cookie auth, no Bearer).
// ─────────────────────────────────────────────────────────────────────────────
export async function pollSunoClips(page, clipIds, timeoutSeconds, deviceId, pollSeconds = 5, onProgress = null) {
const deadline = Date.now() + timeoutSeconds * 1000;
const targetSet = new Set(clipIds);
const idsJson = JSON.stringify(clipIds);
while (Date.now() < deadline) {View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command once — transient proxy/CDN corruption can produce an unparseable body.
- Re-authenticate with Suno (`suno auth login`) and retry, since a stale session can yield unexpected responses.
- Check the Raw/detail output or log the response text to see what the server actually returned.
- Update the opencli suno CLI in case Suno changed the /api/generate/v2-web/ response shape.
Example fix
// before: blindly trusting body shape
const clips = result.body.clips;
// after: guard before use
if (!result.body || typeof result.body !== 'object' || Array.isArray(result.body)) {
throw new CommandExecutionError('Suno generate returned malformed JSON payload.');
}
const clips = result.body?.clips || []; Defensive patterns
Strategy: type-guard
Validate before calling
// check last response shape before trusting it const ok = result && result.ok && result.body && typeof result.body === 'object' && !Array.isArray(result.body);
Type guard
function isSunoGenerateBody(b) {
return !!b && typeof b === 'object' && !Array.isArray(b) && Array.isArray(b.clips);
} Try / catch
try {
const body = await submitSunoGeneration(page, payload);
} catch (e) {
if (e instanceof CommandExecutionError && /malformed JSON payload/.test(e.message)) {
// log raw response and retry once after re-checking session
} else throw e;
} Prevention
- Keep the Suno CLI updated for API shape changes
- Re-authenticate before long-running generation jobs
- Log raw response text on failure for diagnosis
When it happens
Trigger: The /api/generate/v2-web/ fetch returns res.ok true but JSON.parse fails (parsed stays null so result.body is null), or the body parses to an array or primitive instead of an object. Happens when Suno returns HTML/empty/error text with a 2xx status, or an API shape change.
Common situations: Suno deploys an API change returning a different envelope; Cloudflare or a proxy interposes a 2xx HTML page; session/CDN edge cases returning empty bodies; running against a staged/changed Suno endpoint; response truncated by network issues.
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
- Submission accepted but Suno returned no clip ids. Raw: ${JS
- Suno feed API returned malformed JSON while polling clips
- Suno feed API returned malformed clips payload
- Bilibili ${label} API returned a malformed payload
- ${label} returned JSON without result.status.@code
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/58963b1b623e7d20.
Report an issue: GitHub.