jackwener/OpenCLI · error · ArgumentError

Either provide a Simple-mode prompt as the positional argume

Error message

Either provide a Simple-mode prompt as the positional argument, or pass --lyrics for Custom mode.

What it means

An ArgumentError enforcing that `opencli suno generate` needs at least one input: either a positional prompt (Simple mode, where Suno writes lyrics/tags itself) or `--lyrics` (Custom mode). Without either there is nothing to send as the generation `prompt`, which the API requires.

Source

Thrown at clis/suno/generate.js:88

        { name: 'timeout', type: 'int', default: 300, help: 'Max seconds to wait for clips to finish (default: 300)' },
        { name: 'sd', type: 'boolean', default: false, help: 'Skip download; only print clip ids and Suno URLs' },
        { name: 'confirm-paid', type: 'boolean', default: false, help: 'Required to allow paid downloads (wav). Without it, paid formats are skipped with a warning.' },
    ],
    columns: ['status', 'clip', 'title', 'files', 'link'],
    func: async (page, kwargs) => {
        const lyrics = kwargs.lyrics ? String(kwargs.lyrics) : '';
        const tags = kwargs.tags ? String(kwargs.tags) : '';
        const negativeTags = kwargs['negative-tags'] ? String(kwargs['negative-tags']) : '';
        const description = kwargs.prompt ? String(kwargs.prompt) : '';
        const titleArg = kwargs.title ? String(kwargs.title) : '';
        const model = kwargs.model ? String(kwargs.model).trim() : DEFAULT_SUNO_MODEL;
        if (!SUNO_MODELS.includes(model)) {
            throw new ArgumentError(`Unsupported --model "${model}"`, `Choices: ${SUNO_MODELS.join(', ')}`);
        }

        const isCustom = lyrics.trim() !== '';
        if (!isCustom && !description.trim()) {
            throw new ArgumentError(
                'Either provide a Simple-mode prompt as the positional argument, or pass --lyrics for Custom mode.',
                'Examples:\n  opencli suno generate "lo-fi study beat, 80 bpm"\n  opencli suno generate --lyrics "[Verse]\\n..." --tags "synthwave, 120 bpm"',
            );
        }
        if (!isCustom && (tags || negativeTags)) {
            throw new ArgumentError('--tags and --negative-tags only apply in Custom mode (alongside --lyrics).');
        }

        const requestedFormats = parseFormats(kwargs.formats);
        const confirmPaid = normalizeBooleanFlag(kwargs['confirm-paid']);
        const skipDownload = normalizeBooleanFlag(kwargs.sd);
        const PAID_FORMATS = new Set(['wav']);
        const skippedPaid = [];
        const formats = requestedFormats.filter(f => {
            if (PAID_FORMATS.has(f) && !confirmPaid) {
                skippedPaid.push(f);
                return false;
            }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a Simple-mode description as the positional argument: `opencli suno generate "lo-fi study beat, 80 bpm"`.
  2. Or use Custom mode: `opencli suno generate --lyrics "[Verse]..." --tags "synthwave, 120 bpm"`.
  3. If scripting, check the prompt/lyrics variables are non-empty before invoking the command.
  4. Quote the prompt so spaces don't split it into stray positional tokens.

Example fix

// before
opencli suno generate --tags "synthwave"
// after
opencli suno generate "retro synthwave, 110 bpm" --tags "synthwave"  # or add --lyrics for custom mode
Defensive patterns

Strategy: validation

Validate before calling

import { execFileSync } from 'node:child_process';
const prompt = process.argv[2] ?? '';
const lyrics = process.env.LYRICS ?? '';
if (!prompt.trim() && !lyrics.trim()) {
  throw new Error('need a positional prompt or --lyrics');
}
execFileSync('opencli', ['suno', 'generate', prompt].filter(Boolean), { stdio: 'inherit' });

Type guard

const hasInput = (prompt, lyrics) =>
  (typeof prompt === 'string' && prompt.trim() !== '') ||
  (typeof lyrics === 'string' && lyrics.trim() !== '');

Try / catch

try {
  await run('opencli suno generate ' + args);
} catch (err) {
  if (String(err.message).includes('Simple-mode prompt')) {
    // re-invoke with a positional prompt or --lyrics
  } else throw err;
}

Prevention

When it happens

Trigger: Running `opencli suno generate` with no positional prompt and no --lyrics — e.g. only passing flags like --tags/--instrumental/--model, quoting mistakes that drop the positional argument, or shell-embedded prompts expanding to an empty string.

Common situations: Forgetting the positional description, an empty shell variable (`$PROMPT` unset) consumed as the positional arg, or assuming flags alone constitute a request.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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