jackwener/OpenCLI · error · CommandExecutionError

Suno download wrote no files for clip ${clipId}

Error message

Suno download wrote no files for clip ${clipId}

What it means

Thrown by `opencli suno download` after `downloadSunoClip` runs when every requested format write failed (`result.written` has no entry with `ok: true`). The clip was found and complete, but the browser-driven download pipeline produced zero files on disk. Per-write failure reasons are printed in the run summary (`format:✗(reason)`).

Source

Thrown at clis/suno/download.js:120

        })()`));

        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.length
            ? ` | skipped(needs --confirm-paid):${skippedPaid.join(',')}`
            : '';
        const fileSummary = `${writtenSummary}${skippedSummary}`;
        const anyFailed = result.written.some(w => !w.ok);

        return [{
            status: anyFailed ? '⚠ partial' : '✅ saved',
            clip: clip.id.slice(0, 8),
            title: clip.title || '(untitled)',
            files: `📁 ${fileSummary}`,
            link: `🔗 ${link}`,
        }];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command and read the per-format failure reasons in the summary line; fix the specific reason shown.
  2. Verify the output directory (--op, default ~/Music/suno) exists and is writable, and that you have free disk space.
  3. Confirm the driven Chrome profile allows downloads and isn't blocking popups/multiple downloads.
  4. Narrow to a single free format (`--formats mp3`) to isolate whether the failure is format-specific (e.g. CDN or billing) or systemic.
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'node:fs';
// before running: ensure the output dir exists and is writable, and disk has space
const outDir = '/home/me/Music/suno';
fs.mkdirSync(outDir, { recursive: true });
fs.accessSync(outDir, fs.constants.W_OK);

Try / catch

try {
  await run(`opencli suno download ${clipId} --formats mp3,metadata`);
} catch (err) {
  if (String(err.message).includes('wrote no files')) {
    // inspect per-format ✗(reason) summary; fix dir permissions/CDN issue and retry
  } else throw err;
}

Prevention

When it happens

Trigger: Requesting formats (mp3/wav/m4a/video/cover/metadata) where every one failed — e.g. download URLs returned errors, browser save events never fired, the output directory is not writable, or paid formats (wav) were rejected without billing consent.

Common situations: Unwritable or nonexistent --op output directory, disk full, Suno CDN download URL expiring or 403-ing, popup/download interception blocked in the driven Chrome profile, or network drop mid-download.

Related errors


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