{"record":{"id":"43ee9abafc32e49c","repo":"jackwener/OpenCLI","slug":"label-midjourney-job-url-index-must-be-0-3","errorCode":null,"errorMessage":"${label} Midjourney job URL index must be 0..3: ${item}","messagePattern":"(.+?) Midjourney job URL index must be 0\\.\\.3: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":890,"sourceCode":"  } else {\n    items = [raw];\n  }\n  if (!Array.isArray(items) || items.length === 0 || items.some((item) => typeof item !== 'string' || !item.trim())) {\n    throw new ArgumentError(`${label} must contain one or more non-empty strings`);\n  }\n  if (!multiple && items.length !== 1) throw new ArgumentError(`${label} accepts exactly one reference`);\n  return items.map((item) => item.trim()).map((item) => {\n    if (allowStyleCode && /^\\d+$/.test(item)) return { kind: 'styleCode', value: item };\n    if (/^https:\\/\\//i.test(item)) {\n      try {\n        const parsed = new URL(item);\n        const match = parsed.hostname === MIDJOURNEY_DOMAIN\n          ? parsed.pathname.match(/^\\/jobs\\/([0-9a-f-]{36})\\/?$/i)\n          : null;\n        if (match && UUID_RE.test(match[1])) {\n          const index = Number(parsed.searchParams.get('index') || 0);\n          if (!Number.isInteger(index) || index < 0 || index > 3) {\n            throw new ArgumentError(`${label} Midjourney job URL index must be 0..3: ${item}`);\n          }\n          return { kind: 'url', value: originalImageUrl(match[1].toLowerCase(), index), source: item };\n        }\n      } catch (error) {\n        if (error instanceof ArgumentError) throw error;\n      }\n      return { kind: 'url', value: item };\n    }\n    const expanded = item === '~' ? os.homedir() : item.startsWith('~/') ? path.join(os.homedir(), item.slice(2)) : item;\n    return { kind: 'local', value: path.resolve(expanded) };\n  });\n}\n\nexport async function validateLocalReferences(refs, label) {\n  for (const ref of refs.filter((item) => item.kind === 'local')) {\n    let stat;\n    try {\n      stat = await fs.stat(ref.value);","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L872-L908","documentation":"A Midjourney job URL (https://<domain>/jobs/<uuid>?index=N) encodes which result image is referenced via the index query parameter. The parser validates that index is an integer in 0..3 and throws this ArgumentError otherwise, because a 2x2 job grid only has four images.","triggerScenarios":"A job URL whose searchParams contain index=4 or higher, a negative index, a non-integer (index=1.5), or a non-numeric value (index=abc).","commonSituations":"Copy-pasting URLs from the Midjourney web UI which uses 1-based-looking indices (UI's 4th image is index=3 here), hand-editing URLs, or generating URLs programmatically with wrong index math.","solutions":["Set the index query parameter to 0, 1, 2, or 3 (0-based; if the UI shows the 4th image, use index=3)","Remove the index parameter entirely to default to index 0","Re-copy the job URL and adjust the index instead of guessing beyond 3"],"exampleFix":"// before\nhttps://www.midjourney.com/jobs/123e4567-e89b-12d3-a456-426614174000?index=4\n// after\nhttps://www.midjourney.com/jobs/123e4567-e89b-12d3-a456-426614174000?index=3","handlingStrategy":"validation","validationCode":"const url = new URL(refUrl);\nconst idx = Number(url.searchParams.get('index') || 0);\nif (!Number.isInteger(idx) || idx < 0 || idx > 3) {\n  url.searchParams.set('index', '0'); // or clamp/fix before passing\n}","typeGuard":"const hasValidJobIndex = (u) => { const n = Number(new URL(u).searchParams.get('index') ?? 0); return Number.isInteger(n) && n >= 0 && n <= 3; };","tryCatchPattern":"try {\n  const refs = parseReferences('refs', jobUrl, { multiple: false });\n} catch (e) {\n  if (String(e.message).includes('index must be 0..3')) {\n    const fixed = jobUrl.replace(/([?&])index=\\d+/, '$1index=0');\n    console.error('Bad index in job URL; retrying with index=0');\n  }\n}","preventionTips":["Remember the CLI expects 0-based indices (0..3); the Midjourney UI's 4th image is index=3","Sanitize URLs copied from the web UI before passing them","Omit the index parameter to default to 0"],"tags":["argument-validation","url-parsing","cli"],"backgroundTag":"invalid-argument-input","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}