{"record":{"id":"a745b3403ea88db0","repo":"jackwener/OpenCLI","slug":"either-provide-a-simple-mode-prompt-as-the-positio","errorCode":null,"errorMessage":"Either provide a Simple-mode prompt as the positional argument, or pass --lyrics for Custom mode.","messagePattern":"Either provide a Simple-mode prompt as the positional argument, or pass --lyrics for Custom mode\\.","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/suno/generate.js","lineNumber":88,"sourceCode":"        { name: 'timeout', type: 'int', default: 300, help: 'Max seconds to wait for clips to finish (default: 300)' },\n        { name: 'sd', type: 'boolean', default: false, help: 'Skip download; only print clip ids and Suno URLs' },\n        { name: 'confirm-paid', type: 'boolean', default: false, help: 'Required to allow paid downloads (wav). Without it, paid formats are skipped with a warning.' },\n    ],\n    columns: ['status', 'clip', 'title', 'files', 'link'],\n    func: async (page, kwargs) => {\n        const lyrics = kwargs.lyrics ? String(kwargs.lyrics) : '';\n        const tags = kwargs.tags ? String(kwargs.tags) : '';\n        const negativeTags = kwargs['negative-tags'] ? String(kwargs['negative-tags']) : '';\n        const description = kwargs.prompt ? String(kwargs.prompt) : '';\n        const titleArg = kwargs.title ? String(kwargs.title) : '';\n        const model = kwargs.model ? String(kwargs.model).trim() : DEFAULT_SUNO_MODEL;\n        if (!SUNO_MODELS.includes(model)) {\n            throw new ArgumentError(`Unsupported --model \"${model}\"`, `Choices: ${SUNO_MODELS.join(', ')}`);\n        }\n\n        const isCustom = lyrics.trim() !== '';\n        if (!isCustom && !description.trim()) {\n            throw new ArgumentError(\n                'Either provide a Simple-mode prompt as the positional argument, or pass --lyrics for Custom mode.',\n                'Examples:\\n  opencli suno generate \"lo-fi study beat, 80 bpm\"\\n  opencli suno generate --lyrics \"[Verse]\\\\n...\" --tags \"synthwave, 120 bpm\"',\n            );\n        }\n        if (!isCustom && (tags || negativeTags)) {\n            throw new ArgumentError('--tags and --negative-tags only apply in Custom mode (alongside --lyrics).');\n        }\n\n        const requestedFormats = parseFormats(kwargs.formats);\n        const confirmPaid = normalizeBooleanFlag(kwargs['confirm-paid']);\n        const skipDownload = normalizeBooleanFlag(kwargs.sd);\n        const PAID_FORMATS = new Set(['wav']);\n        const skippedPaid = [];\n        const formats = requestedFormats.filter(f => {\n            if (PAID_FORMATS.has(f) && !confirmPaid) {\n                skippedPaid.push(f);\n                return false;\n            }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/suno/generate.js#L70-L106","documentation":"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.","triggerScenarios":"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.","commonSituations":"Forgetting the positional description, an empty shell variable (`$PROMPT` unset) consumed as the positional arg, or assuming flags alone constitute a request.","solutions":["Pass a Simple-mode description as the positional argument: `opencli suno generate \"lo-fi study beat, 80 bpm\"`.","Or use Custom mode: `opencli suno generate --lyrics \"[Verse]...\" --tags \"synthwave, 120 bpm\"`.","If scripting, check the prompt/lyrics variables are non-empty before invoking the command.","Quote the prompt so spaces don't split it into stray positional tokens."],"exampleFix":"// before\nopencli suno generate --tags \"synthwave\"\n// after\nopencli suno generate \"retro synthwave, 110 bpm\" --tags \"synthwave\"  # or add --lyrics for custom mode","handlingStrategy":"validation","validationCode":"import { execFileSync } from 'node:child_process';\nconst prompt = process.argv[2] ?? '';\nconst lyrics = process.env.LYRICS ?? '';\nif (!prompt.trim() && !lyrics.trim()) {\n  throw new Error('need a positional prompt or --lyrics');\n}\nexecFileSync('opencli', ['suno', 'generate', prompt].filter(Boolean), { stdio: 'inherit' });","typeGuard":"const hasInput = (prompt, lyrics) =>\n  (typeof prompt === 'string' && prompt.trim() !== '') ||\n  (typeof lyrics === 'string' && lyrics.trim() !== '');","tryCatchPattern":"try {\n  await run('opencli suno generate ' + args);\n} catch (err) {\n  if (String(err.message).includes('Simple-mode prompt')) {\n    // re-invoke with a positional prompt or --lyrics\n  } else throw err;\n}","preventionTips":["Always pass the prompt in quotes so shell word-splitting doesn't drop it.","In scripts, assert prompt/lyrics variables are non-empty before invoking.","Remember flags alone never constitute a generation request."],"tags":["suno","cli","argument-validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}