jackwener/OpenCLI · error · TimeoutError

Midjourney job submission

Error message

Midjourney job submission

What it means

TimeoutError thrown when the overall --timeout budget (default 300s, max 900s) is exhausted before the job could even be confirmed as submitted — i.e. remainingForSubmission computed from (Date.now() - commandStartedAt) drops below 1 second right after pressing Enter. The name 'Midjourney job submission' indicates the deadline hit during the submission-confirmation phase, not during generation.

Source

Thrown at clis/midjourney/generate.js:200

    if (typeof page.installInterceptor === 'function' && typeof page.getInterceptedRequests === 'function') {
      try {
        await page.installInterceptor('/api/submit-jobs');
        await page.getInterceptedRequests();
        captureReady = true;
      } catch {}
    }

    const submittedAt = Date.now();
    try {
      const filled = await page.fillText(COMPOSER_SELECTOR, effectivePrompt);
      if (!filled?.filled || !filled?.verified) throw new Error('composer fill was not verified');
      await page.pressKey('Enter');
    } catch (error) {
      throw new CommandExecutionError(`Could not submit the Midjourney prompt: ${error instanceof Error ? error.message : String(error)}`);
    }

    const remainingForSubmission = Math.floor(timeout - (Date.now() - commandStartedAt) / 1000);
    if (remainingForSubmission < 1) throw new TimeoutError('Midjourney job submission', timeout);
    const submitTimeout = Math.min(remainingForSubmission, 75);
    let jobIds = [];
    if (captureReady && typeof page.waitForCapture === 'function') {
      try {
        await page.waitForCapture(Math.min(submitTimeout, 20));
        jobIds = submittedJobIdsFromCaptures(await page.getInterceptedRequests(), plan.repeat, baselineIds);
      } catch (error) {
        if (error instanceof CommandExecutionError) throw error;
      }
    }
    if (!jobIds.length) {
      jobIds = await waitForSubmittedJobsAfter(
        page,
        account.user_id,
        effectivePrompt,
        baselineIds,
        submitTimeout,
        submittedAt,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Increase --timeout (up to 900) to leave room for uploads plus submission confirmation
  2. Reduce upload cost — drop --image-ref/--style-ref/--omni-ref or use HTTPS URLs instead of large local files
  3. Run with --wait false and --skip-download so the budget is spent only on submission
  4. Check network speed to midjourney.com; slow uploads are the usual budget consumer

Example fix

// before
opencli midjourney generate "prompt" --image-ref ./big.png --timeout 30
// after
opencli midjourney generate "prompt" --image-ref ./big.png --timeout 600
Defensive patterns

Strategy: validation

Validate before calling

const TIMEOUT = 600; // seconds
const largeLocalRefs = [imageRef, ...styleRefs].filter((p) => !/^https?:/.test(p));
const totalMb = largeLocalRefs.reduce((s, p) => s + fs.statSync(p).size / 1e6, 0);
// Rough guard: uploads+setup need headroom before submission can be confirmed.
if (totalMb > 20 && TIMEOUT < 300) {
  throw new Error(`--timeout ${TIMEOUT}s too small for ${totalMb.toFixed(0)}MB of reference uploads; use >= 600`);
}

Type guard

function willLikelyTimeOut(timeoutSeconds, uploadBytes) {
  const setupSeconds = 30 + (uploadBytes / (2 * 1024 * 1024)); // ~2 MB/s heuristic
  return timeoutSeconds <= setupSeconds + 45; // +45s submission-confirmation window
}

Try / catch

try {
  await generate(prompt, { timeout: 600 });
} catch (e) {
  if (/Midjourney job submission/.test(e.message) || e.name === 'TimeoutError') {
    // Submission may or may not have gone through — check history before resubmitting
    const dupes = await fetchRecentJobs(prompt);
    if (!dupes.length) await generate(prompt, { timeout: 900, wait: false });
  } else throw e;
}

Prevention

When it happens

Trigger: Uploading local image/style/omni references via uploadReferencesToSlot, waiting for the composer, and clearImagePrompts consumed nearly the entire --timeout before submission was attempted, leaving <1s to confirm the submit-jobs request. Common with large reference files, many --repeat jobs, or a very small --timeout value (e.g. --timeout 10).

Common situations: Users passing --timeout 30 or lower while also uploading several large reference images; slow network uploads to Midjourney's slots; the persistent browser being cold/slow so composer setup ate the budget; retrying a command whose earlier phases were slow.

Related errors


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