jackwener/OpenCLI · error · ArgumentError

${label} Midjourney job URL index must be 0..3: ${item}

Error message

${label} Midjourney job URL index must be 0..3: ${item}

What it means

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.

Source

Thrown at clis/midjourney/utils.js:890

  } else {
    items = [raw];
  }
  if (!Array.isArray(items) || items.length === 0 || items.some((item) => typeof item !== 'string' || !item.trim())) {
    throw new ArgumentError(`${label} must contain one or more non-empty strings`);
  }
  if (!multiple && items.length !== 1) throw new ArgumentError(`${label} accepts exactly one reference`);
  return items.map((item) => item.trim()).map((item) => {
    if (allowStyleCode && /^\d+$/.test(item)) return { kind: 'styleCode', value: item };
    if (/^https:\/\//i.test(item)) {
      try {
        const parsed = new URL(item);
        const match = parsed.hostname === MIDJOURNEY_DOMAIN
          ? parsed.pathname.match(/^\/jobs\/([0-9a-f-]{36})\/?$/i)
          : null;
        if (match && UUID_RE.test(match[1])) {
          const index = Number(parsed.searchParams.get('index') || 0);
          if (!Number.isInteger(index) || index < 0 || index > 3) {
            throw new ArgumentError(`${label} Midjourney job URL index must be 0..3: ${item}`);
          }
          return { kind: 'url', value: originalImageUrl(match[1].toLowerCase(), index), source: item };
        }
      } catch (error) {
        if (error instanceof ArgumentError) throw error;
      }
      return { kind: 'url', value: item };
    }
    const expanded = item === '~' ? os.homedir() : item.startsWith('~/') ? path.join(os.homedir(), item.slice(2)) : item;
    return { kind: 'local', value: path.resolve(expanded) };
  });
}

export async function validateLocalReferences(refs, label) {
  for (const ref of refs.filter((item) => item.kind === 'local')) {
    let stat;
    try {
      stat = await fs.stat(ref.value);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Set the index query parameter to 0, 1, 2, or 3 (0-based; if the UI shows the 4th image, use index=3)
  2. Remove the index parameter entirely to default to index 0
  3. Re-copy the job URL and adjust the index instead of guessing beyond 3

Example fix

// before
https://www.midjourney.com/jobs/123e4567-e89b-12d3-a456-426614174000?index=4
// after
https://www.midjourney.com/jobs/123e4567-e89b-12d3-a456-426614174000?index=3
Defensive patterns

Strategy: validation

Validate before calling

const url = new URL(refUrl);
const idx = Number(url.searchParams.get('index') || 0);
if (!Number.isInteger(idx) || idx < 0 || idx > 3) {
  url.searchParams.set('index', '0'); // or clamp/fix before passing
}

Type guard

const hasValidJobIndex = (u) => { const n = Number(new URL(u).searchParams.get('index') ?? 0); return Number.isInteger(n) && n >= 0 && n <= 3; };

Try / catch

try {
  const refs = parseReferences('refs', jobUrl, { multiple: false });
} catch (e) {
  if (String(e.message).includes('index must be 0..3')) {
    const fixed = jobUrl.replace(/([?&])index=\d+/, '$1index=0');
    console.error('Bad index in job URL; retrying with index=0');
  }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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