jackwener/OpenCLI · error · CommandExecutionError

Suno generation returned malformed clip identity.

Error message

Suno generation returned malformed clip identity.

What it means

The CLI maps submission.clips to their ids and throws if any clip is missing an id. Suno returned clip objects but at least one lacks a usable identity, so polling/downloading that clip would be impossible.

Source

Thrown at clis/suno/generate.js:174

            lyrics,
            tags,
            negativeTags,
            description,
            makeInstrumental,
            weirdness,
            styleWeight,
            userTier: session.planId,
            createSessionToken,
            transactionUuid,
            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}`,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Dump submission.clips to inspect the malformed entries and confirm the schema drift.
  2. Check whether Suno renamed the clip id field (e.g. id → clipId) and update the mapping.
  3. Retry the generation — a transient server glitch may have produced a partial payload.
  4. Filter out clips without ids as a workaround, if partial results are acceptable.

Example fix

// before
const clipIds = submission.clips.map(c => c?.id);
// after: tolerate partial entries
const clipIds = submission.clips.map(c => c?.id).filter(Boolean);
Defensive patterns

Strategy: type-guard

Validate before calling

const clipIds = (submission.clips || []).map(c => c?.id).filter(id => typeof id === 'string' && id);
if (clipIds.length !== submission.clips.length) console.warn('some clips missing ids', submission.clips);

Type guard

function isClipWithId(c) { return !!c && typeof c === 'object' && typeof c.id === 'string' && c.id.length > 0; }

Try / catch

try {
  const ids = submission.clips.map(c => { if (!isClipWithId(c)) throw new Error('clip without id'); return c.id; });
} catch (e) {
  if (/without id/.test(e.message)) { dumpPayloadForDebugging(submission); }
  throw e;
}

Prevention

When it happens

Trigger: `submission.clips.map(c => c?.id)` yields at least one falsy id — a clip entry is null, undefined, or has no id field.

Common situations: Suno partially updated its clip object schema (id renamed/moved), or returned placeholder entries for clips that were rejected server-side.

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/0851d170a53f5a4a. Report an issue: GitHub.