jackwener/OpenCLI · error · CommandExecutionError

Midjourney cancel request failed: HTTP ${result?.status ?? 0

Error message

Midjourney cancel request failed: HTTP ${result?.status ?? 0}${result?.body ? ` ${result.body}` : ''}

What it means

When the cancel request returns a non-OK status other than 401/403, cancelMidjourneyJob throws CommandExecutionError including the HTTP status and any response body. This surfaces server-side rejection (404 unknown job, 429 rate limit, 5xx) with maximum detail for debugging.

Source

Thrown at clis/midjourney/utils.js:375

export async function cancelMidjourneyJob(page, jobId) {
  let result;
  try {
    result = unwrapEvaluateResult(await page.evaluate(async (id) => {
      const response = await fetch('/api/job-cancel', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-CSRF-Protection': '1' },
        body: JSON.stringify({ job_id: id }),
      });
      return { ok: response.ok, status: response.status, body: await response.text() };
    }, jobId));
  } catch (error) {
    throw new CommandExecutionError(`Midjourney cancel request failed: ${errorMessage(error)}`);
  }
  if (!result?.ok) {
    if ([401, 403].includes(Number(result?.status))) {
      throw new AuthRequiredError(MIDJOURNEY_DOMAIN, 'Log into Midjourney in Chrome, then retry.');
    }
    throw new CommandExecutionError(
      `Midjourney cancel request failed: HTTP ${result?.status ?? 0}${result?.body ? ` ${result.body}` : ''}`,
    );
  }
  return result;
}

export async function getVisibleJobIds(page) {
  const payload = unwrapEvaluateResult(await page.evaluate(() => {
    const ids = new Set();
    for (const link of document.querySelectorAll('a[href*="/jobs/"]')) {
      const match = String(link.getAttribute('href') || '').match(/\/jobs\/([0-9a-f-]{36})/i);
      if (match) ids.add(match[1].toLowerCase());
    }
    return [...ids];
  }));
  return Array.isArray(payload) ? payload.filter((id) => UUID_RE.test(id)) : [];
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the HTTP status and body in the message: 404 → verify the job ID exists; 429 → wait and retry with backoff; 5xx → retry later or check Midjourney status.
  2. Confirm the job is not already completed/cancelled — many endpoints reject cancelling terminal jobs.
  3. Retry after a delay with exponential backoff for 429/5xx responses.
  4. If 404 persists while the job is visible on midjourney.com, the cancel endpoint contract likely changed; update the adapter.

Example fix

// before
await cancelMidjourneyJob(page, jobId);
// after
try {
  await cancelMidjourneyJob(page, jobId);
} catch (e) {
  if (/HTTP 429/.test(String(e.message))) {
    await new Promise((r) => setTimeout(r, 5000));
    await cancelMidjourneyJob(page, jobId); // backoff retry for rate limit
  } else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// check the job is still cancellable (not already terminal) before calling
const job = await fetchJobStatus(page, jobId, { allowMissing: true });
if (!job) throw new Error(`Job ${jobId} not found — cancel would 404.`);
const st = String(job.current_status || job.status || '').toLowerCase();
if (['completed', 'cancelled', 'canceled', 'failed'].includes(st)) throw new Error(`Job already ${st}; skip cancel.`);

Type guard

function isRetryableHttpError(err) {
  return /HTTP (429|5\d\d)/.test(String(err.message));
}

Try / catch

async function cancelWithRetry(page, jobId, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try { return await cancelMidjourneyJob(page, jobId); }
    catch (e) {
      if (isRetryableHttpError(e) && i < attempts - 1) {
        await new Promise((r) => setTimeout(r, 2000 * 2 ** i)); // backoff for 429/5xx
        continue;
      }
      throw e;
    }
  }
}

Prevention

When it happens

Trigger: Cancel endpoint responds 404 (job ID not found or endpoint path changed), 429 (rate limited), or 5xx (Midjourney server error); response.ok is false and status is not 401/403.

Common situations: Typo'd or already-cancelled job IDs (404); cancelling many jobs in rapid succession (429); Midjourney API outages or deploy regressions (5xx); endpoint path renamed in a site update.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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