{"record":{"id":"1eae95ae20799197","repo":"jackwener/OpenCLI","slug":"midjourney-job-jobid-is-status-missing","errorCode":null,"errorMessage":"Midjourney job ${jobId} is \"${status || 'missing'}\"; media is available after completion.","messagePattern":"Midjourney job (.+?) is \"(.+?)\"; media is available after completion\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/download.js","lineNumber":43,"sourceCode":"  strategy: Strategy.COOKIE,\n  browser: true,\n  siteSession: 'persistent',\n  navigateBefore: 'https://www.midjourney.com/imagine',\n  defaultFormat: 'plain',\n  args: [\n    { name: 'job', positional: true, required: true, help: 'Job UUID or Midjourney /jobs/<uuid> URL' },\n    { name: 'index', default: 'all', help: 'Candidate 1..4 or all' },\n    { name: 'kind', default: 'auto', help: 'auto, image, video-raw, video-social, or gif' },\n    { name: 'output', default: '~/Pictures/Midjourney', help: 'Output directory' },\n    { name: 'force', type: 'boolean', default: false, help: 'Overwrite existing non-empty files' },\n  ],\n  columns: ['job_id', 'status', 'kind', 'index', 'file', 'bytes', 'mime', 'url'],\n  func: async (page, kwargs) => {\n    const jobId = parseJobId(kwargs.job);\n    const job = await fetchJobStatus(page, jobId);\n    const status = String(job.current_status || job.status || '').toLowerCase();\n    if (status !== 'completed') {\n      throw new CommandExecutionError(`Midjourney job ${jobId} is \"${status || 'missing'}\"; media is available after completion.`);\n    }\n    const video = isVideoJob(job);\n    let kind = String(kwargs.kind || 'auto').trim().toLowerCase();\n    if (!KINDS.includes(kind)) throw new ArgumentError(`--kind must be one of: ${KINDS.join(', ')}`);\n    if (kind === 'auto') kind = video ? 'video-raw' : 'image';\n    if (video && kind === 'image') throw new ArgumentError('Video jobs support video-raw, video-social, or gif downloads');\n    if (!video && kind !== 'image') throw new ArgumentError('Image jobs only support --kind image');\n\n    const indices = parseImageIndices(kwargs.index, Number(job.batch_size || (video ? 1 : 4)));\n    const outputDir = resolveOutputDir(kwargs.output);\n    const force = normalizeBoolean(kwargs.force);\n    let files;\n    if (kind === 'image') {\n      files = (await downloadOriginals(page, jobId, indices, outputDir, force)).map((item) => ({\n        ...item,\n        kind: 'image',\n      }));\n    } else if (kind === 'video-raw') {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/download.js#L25-L61","documentation":"This CommandExecutionError is thrown when fetchJobStatus returns a Midjourney job whose status is anything other than 'completed'. Media files only exist for finished jobs, so the download command refuses to proceed and reports the job's actual status (or 'missing' when the status field is empty).","triggerScenarios":"Calling `opencli midjourney download <job>` while the job's current_status/status (lowercased) is e.g. 'processing', 'queued', 'failed', or absent — the fetch returned no completed job for that UUID.","commonSituations":"Polling for a job right after submitting an imagine/video prompt; a typo'd or wrong job UUID returning a missing status; a failed/canceled job that will never complete; a stale session where the job belongs to another workspace.","solutions":["Wait for the job to finish (poll `opencli midjourney status <job>` or fetchJobStatus) and re-run the download once status is 'completed'","Verify the job ID/URL is correct — a wrong UUID yields a 'missing' status","Check the job in the Midjourney web UI; if it failed or was canceled, resubmit the prompt instead of retrying the download","Re-authenticate the session if the job exists but its status cannot be read"],"exampleFix":"// before\nopencli midjourney download abc123 --kind image\n// Error: job is \"processing\"\n// after: wait until completed\nwhile [ \"$(opencli midjourney status abc123 --format json | jq -r .status)\" != \"completed\" ]; do sleep 5; done\nopencli midjourney download abc123 --kind image","handlingStrategy":"validation","validationCode":"// Check job status before attempting download\nconst job = await fetchJobStatus(page, parseJobId(jobRef));\nconst status = String(job.current_status || job.status || '').toLowerCase();\nif (status !== 'completed') {\n  throw new Error(`Job not ready (status: ${status || 'missing'}). Wait for completion.`);\n}","typeGuard":"function isCompletedJob(job) {\n  return !!job && String(job.current_status || job.status || '').toLowerCase() === 'completed';\n}","tryCatchPattern":"try {\n  await run('midjourney', 'download', jobId);\n} catch (err) {\n  if (err.message.includes('media is available after completion')) {\n    // poll status until completed, then retry the download\n  } else throw err;\n}","preventionTips":["Poll job status until 'completed' before downloading","Double-check the job UUID/URL — 'missing' status usually means a wrong ID","Treat failed/canceled jobs as terminal instead of retrying downloads","Verify the session can see the job's workspace"],"tags":["job-status","midjourney","download"],"backgroundTag":"job-not-completed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}