jackwener/OpenCLI · error · CommandExecutionError

Suno download wrote no files for clip ${clip.id}

Error message

Suno download wrote no files for clip ${clip.id}

What it means

For each completed clip, `downloadSunoClip()` attempts every requested format; if not a single file was written successfully (all writes failed), the CLI throws. This guarantees the command never silently reports success with zero downloaded files.

Source

Thrown at clis/suno/generate.js:212

                    title: clip.title || '(untitled)',
                    files: '-',
                    link: `🔗 ${link}`,
                });
                continue;
            }
            if (skipDownload) {
                rows.push({
                    status: '🎵 generated',
                    clip: clip.id.slice(0, 8),
                    title: clip.title || '(untitled)',
                    files: '📁 -',
                    link: `🔗 ${link}`,
                });
                continue;
            }
            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 ${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 anyFailed = result.written.some(w => !w.ok);
            rows.push({
                status: anyFailed ? '⚠ partial' : '✅ saved',
                clip: clip.id.slice(0, 8),
                title: clip.title || '(untitled)',
                files: `📁 ${writtenSummary}${skippedSummary}`,
                link: `🔗 ${link}`,
            });
        }
        return rows;
    },

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run and pass free formats explicitly, e.g. --formats mp3,metadata (wav requires --confirm-paid true).
  2. Verify cookies/session are still valid and re-login if audio asset requests return 401/403.
  3. Check the output directory (-p/--op) exists and is writable.
  4. Retry shortly after generation so the CDN URLs haven't expired; report failures per format shown as ✗(reason).

Example fix

// before: wav only, silently filtered out without --confirm-paid
$ opencli suno generate "beat" --formats wav
// after
$ opencli suno generate "beat" --formats mp3,metadata
// or allow paid: --formats wav --confirm-paid true
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at least one free, downloadable format is requested:
const formats = parseFormats(kwargs.formats).filter(f => f !== 'wav' || confirmPaid);
if (!skipDownload && !formats.some(f => ['mp3', 'm4a', 'metadata'].includes(f))) {
  throw new Error('add a free format (mp3/metadata) or pass --confirm-paid true');
}
// and verify the output dir is writable:
await fs.promises.access(outputDir, fs.constants.W_OK);

Type guard

function hasWrittenFile(result) { return Array.isArray(result?.written) && result.written.some(w => w?.ok === true); }

Try / catch

try {
  const rows = await opencli('suno', 'generate', prompt, '--formats', 'mp3,metadata');
} catch (e) {
  if (/wrote no files for clip/.test(e.message)) {
    await reloginIfCookiesExpired();
    await retryDownloadSoon(clipId); // retry before CDN URLs expire
  } else throw e;
}

Prevention

When it happens

Trigger: `result.written.every(w => !w.ok)` for a completed clip — every requested format failed to download (auth expired, audio URL 403/404, disk error, or only paid formats requested without --confirm-paid so nothing was attempted).

Common situations: CDN audio URLs expired before download, cookies lost mid-run, output directory not writable, or requesting wav (paid) without --confirm-paid so formats list became empty of downloadable media.

Related errors


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