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

  1. Update the opencli suno CLI to match the current Suno feed schema.
  2. Log result.body keys to discover where the clips array moved (e.g. body.data.clips).
  3. Retry in case a transient backend error object was returned with 200.
  4. 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

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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/8794cacb29a6e090. Report an issue: GitHub.