{"record":{"id":"15f601c6029c12cf","repo":"jackwener/OpenCLI","slug":"invalid-clip-id-raw","errorCode":null,"errorMessage":"Invalid clip-id: ${raw}","messagePattern":"Invalid clip-id: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/suno/download.js","lineNumber":43,"sourceCode":"function displayPath(filePath) {\n    if (!filePath) return '-';\n    const home = os.homedir();\n    return filePath.startsWith(home) ? `~${filePath.slice(home.length)}` : filePath;\n}\n\nfunction parseClipId(value) {\n    const raw = String(value || '').trim();\n    if (!raw) throw new ArgumentError('clip-id required (UUID or /song/<id> URL)');\n    const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n    if (uuidPattern.test(raw)) return raw.toLowerCase();\n    try {\n        const parsed = new URL(raw);\n        const pathMatch = parsed.pathname.match(/^\\/song\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\/?$/i);\n        if (parsed.protocol === 'https:' && parsed.hostname === 'suno.com' && pathMatch) {\n            return pathMatch[1].toLowerCase();\n        }\n    } catch {}\n    throw new ArgumentError(`Invalid clip-id: ${raw}`, 'Pass a UUID or a https://suno.com/song/<uuid> URL.');\n}\n\nexport const downloadCommand = cli({\n    site: 'suno',\n    name: 'download',\n    access: 'write',\n    description: 'Download an existing Suno clip (MP3 + optional WAV/M4A/video) by id',\n    domain: SUNO_DOMAIN,\n    strategy: Strategy.COOKIE,\n    browser: true,\n    siteSession: 'persistent',\n    navigateBefore: false,\n    defaultFormat: 'plain',\n    args: [\n        { name: 'clip', positional: true, required: true, help: 'Clip UUID or https://suno.com/song/<id> URL' },\n        { name: 'formats', help: 'Comma-separated formats: mp3, m4a, wav, video, cover, metadata. Default: mp3,metadata' },\n        { name: 'op', help: 'Output directory (default: ~/Music/suno)' },\n        { name: 'confirm-paid', type: 'boolean', default: false, help: 'Required to allow paid downloads (wav). Without it, paid formats are skipped with a warning.' },","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/suno/download.js#L25-L61","documentation":"parseClipId() accepts either a bare UUID (case-insensitive hex pattern) or an exact https://suno.com/song/<uuid> URL. Anything else — malformed UUID, wrong hostname/path, non-https URL, or unparseable string — throws ArgumentError with the offending value and a hint about the accepted formats.","triggerScenarios":"Passing a full song page URL with extra path/query (e.g. ?shuffle=true), an http:// URL, a suno.org or www hostname, a truncated id, or an internal numeric id instead of the UUID.","commonSituations":"Copying a share link with tracking query params; using the song's slug URL (/song/title-slug) instead of the canonical UUID URL; pasting an embed URL; old bookmark with a different domain.","solutions":["Use the canonical https://suno.com/song/<uuid> URL (strip query strings) or just the UUID","Extract the UUID from a longer URL manually and pass the UUID alone","Note www.suno.com and non-https variants are rejected — use https://suno.com exactly"],"exampleFix":"// before\nawait cli('suno', 'download', 'https://suno.com/song/abc123?utm=x');\n// -> ArgumentError: Invalid clip-id\n// after\nconst m = url.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);\nawait cli('suno', 'download', m[0]);","handlingStrategy":"validation","validationCode":"const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nfunction extractClipId(input) {\n  const raw = String(input || '').trim();\n  if (UUID.test(raw)) return raw.toLowerCase();\n  const m = raw.match(/https:\\/\\/suno\\.com\\/song\\/([0-9a-f-]{36})/i);\n  if (m) return m[1].toLowerCase();\n  throw new Error(`Not a valid clip id: ${raw}`);\n}","typeGuard":"function isValidClipId(v) {\n  return typeof v === 'string' &&\n    (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v.trim()) ||\n     /^https:\\/\\/suno\\.com\\/song\\/[0-9a-f-]{36}\\/?$/i.test(v.trim()));\n}","tryCatchPattern":"try {\n  await cli('suno', 'download', clipInput);\n} catch (e) {\n  if (/Invalid clip-id/.test(e.message)) {\n    const uuid = clipInput.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);\n    if (uuid) return cli('suno', 'download', uuid[0].toLowerCase());\n  }\n  throw e;\n}","preventionTips":["Normalize share links: strip query strings before passing URLs","Use the canonical https://suno.com/song/<uuid> form (no www, no http)","Extract UUIDs with a regex when handling arbitrary pasted links","Store bare UUIDs in scripts instead of full URLs"],"tags":["validation","argument","url","suno"],"backgroundTag":"invalid-argument-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}