jackwener/OpenCLI · error · TimeoutError

Midjourney generation

Error message

Midjourney generation

What it means

TimeoutError('Midjourney generation', timeout) is thrown in `opencli midjourney generate` when the shared --timeout budget is exhausted while waiting for submitted jobs to finish rendering. The job(s) were successfully submitted to Midjourney, but the overall command wall-clock deadline (default per the command's timeout arg, split across submission + per-job polling via waitForCompletedJob) ran out before every job reached 'completed'. The message includes the job id so no work is lost — the job may still complete server-side.

Source

Thrown at clis/midjourney/generate.js:238

      );
    }

    if (!normalizeBoolean(kwargs.wait, true)) {
      const after = await getMidjourneyAccount(page);
      await recordQuotaSnapshot(after, 'generate-after-submit');
      return jobIds.map((jobId) => resultBase(plan, {
        jobId,
        status: 'submitted',
        observedMinutes: observedMinutes(account, after),
        url: jobUrl(jobId),
      }));
    }

    const jobs = [];
    for (const jobId of jobIds) {
      const remainingSeconds = Math.floor(timeout - (Date.now() - commandStartedAt) / 1000);
      if (remainingSeconds < 1) {
        throw new TimeoutError(
          'Midjourney generation',
          timeout,
          `Submitted job ${jobId}; check it with \`opencli midjourney status ${jobId}\`.`,
        );
      }
      jobs.push(await waitForCompletedJob(page, jobId, remainingSeconds));
    }
    const after = await getMidjourneyAccount(page);
    await recordQuotaSnapshot(after, 'generate-after');
    const observed = observedMinutes(account, after);

    if (normalizeBoolean(kwargs['skip-download'])) {
      return jobIds.map((jobId) => resultBase(plan, {
        jobId,
        status: 'completed',
        observedMinutes: observed,
        url: jobUrl(jobId),
      }));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run `opencli midjourney status <jobId>` (or `download`) with the job id from the error message — the job keeps rendering server-side and is not lost.
  2. Retry the command with a larger --timeout (e.g. --timeout 600) so submission + rendering fit in the budget.
  3. Generate fewer images at once (avoid --repeat / lower batch) so per-job waits fit in one timeout window.
  4. Use --no-wait (wait=false) to return immediately after submission with 'submitted' status, then poll `midjourney status` separately.
  5. Check Midjourney queue/subscription speed (fast vs relax mode) at midjourney.com/account if renders are consistently slow.

Example fix

// before
opencli midjourney generate "a blue ceramic teapot" --timeout 60
// after
opencli midjourney generate "a blue ceramic teapot" --timeout 600
# or submit without waiting:
# opencli midjourney generate "a blue ceramic teapot" --no-wait
Defensive patterns

Strategy: try-catch

Validate before calling

// Before a long batch, budget the timeout against expected render time:
const expectedSeconds = jobCount * 90; // ~90s per image
if (timeout < expectedSeconds) throw new Error(`--timeout ${timeout}s too small for ${jobCount} job(s); use >= ${expectedSeconds}`);

Type guard

function isTimeoutError(e) { return e instanceof TimeoutError || (e && e.name === 'TimeoutError' && /Midjourney generation/.test(e.message ?? '')); }

Try / catch

import { TimeoutError } from '@jackwener/opencli/errors';
try {
  await opencli.midjourney.generate({ prompt, timeout: 600 });
} catch (e) {
  if (isTimeoutError(e)) {
    const jobId = e.message.match(/job ([0-9a-f-]{36})/i)?.[1];
    // job still renders server-side — poll instead of retrying the paid generation
    return pollStatus(jobId);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `opencli midjourney generate` with --wait enabled (the default) where (Date.now() - commandStartedAt)/1000 >= timeout before the loop reaches a job, or a previous job in the batch consumed the entire budget leaving <1 second for the next jobId; slow Midjourney renders (large batches, --repeat, relax mode queueing) or many jobs against one shared timeout.

Common situations: User passes a small --timeout (e.g. 60s) while Midjourney queue is long; generating a multi-image batch where the first image takes almost the whole timeout; running in relax mode during peak hours when jobs sit queued for minutes; slow network/Browser Bridge polling adding latency.

Related errors


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