{"record":{"id":"d19f1bd9cd32f3af","repo":"jackwener/OpenCLI","slug":"failed-to-download-grok-image-img-src-reason","errorCode":null,"errorMessage":"Failed to download grok image ${img.src}${reason}","messagePattern":"Failed to download grok image (.+?)(.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"critical","filePath":"clis/grok/image.js","lineNumber":214,"sourceCode":"      let binary = '';\n      for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n      return { ok: true, base64: btoa(binary), contentType: blob.type || 'image/jpeg' };\n    } catch (e) { return { ok: false, error: e && e.message || String(e) }; }\n  })()`);\n}\n\nasync function saveImages(page, images, outDir) {\n  fs.mkdirSync(outDir, { recursive: true });\n  const results = [];\n  for (const img of images) {\n    const fetched = await fetchImageAsBase64(page, img.src);\n    if (!fetched || !fetched.ok) {\n      // Fail loudly on per-image download failure rather than emit a sentinel\n      // row with path = '[DOWNLOAD FAILED] ...' that downstream tools cannot\n      // distinguish from a real path. assets.grok.com is Cloudflare-gated, so\n      // a single 401/403 typically means the whole batch is unrecoverable.\n      const reason = fetched?.error ? `: ${fetched.error}` : '';\n      throw new CommandExecutionError(\n        `Failed to download grok image ${img.src}${reason}`,\n        'assets.grok.com download requires the live grok.com browser session — verify the tab is logged in and try again.',\n      );\n    }\n    const filepath = path.join(outDir, buildFilename(img.src, fetched.contentType));\n    fs.writeFileSync(filepath, Buffer.from(fetched.base64 || '', 'base64'));\n    results.push({ ...img, path: filepath });\n  }\n  return results;\n}\n\nfunction toRow(img, savedPath = '') {\n  return { url: img.src, width: img.w, height: img.h, path: savedPath };\n}\n\nexport const imageCommand = cli({\n  site: 'grok',\n  name: 'image',","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/grok/image.js#L196-L232","documentation":"saveImages throws CommandExecutionError when an individual image fetch from assets.grok.com fails (non-OK HTTP or fetch error). The library fails loudly instead of writing a '[DOWNLOAD FAILED]' sentinel row because assets.grok.com is Cloudflare-gated — one 401/403 usually means the entire batch is unrecoverable. The remediation hint points at the live grok.com browser session.","triggerScenarios":"Downloading generated images while the fetch to assets.grok.com returns !ok (401/403/404/timeouts) or the fetch wrapper reports an error; saveImages is invoked by the image command after generation when an outDir is provided.","commonSituations":"Expired or logged-out grok.com browser session so Cloudflare blocks asset requests; transient CDN 5xx; hotlink protection; the image URL expiring shortly after generation.","solutions":["Verify the grok.com tab the automation drives is logged in, then retry.","Re-run the command — Cloudflare/CDN failures are often transient.","Regenerate the image if its asset URL has expired.","If a corporate proxy/VPN interferes, retry from a network that can reach assets.grok.com."],"exampleFix":"// before (logged-out tab)\ncli image --out ./imgs   # 401 from assets.grok.com\n// after\n// log into grok.com in the automated browser tab, then\ncli image --out ./imgs","handlingStrategy":"retry","validationCode":"// Pre-check session before generating images:\nconst loggedIn = await page.evaluate(() => !!document.querySelector('[data-testid=\"composer\"]'));\nif (!loggedIn) throw new Error('grok.com session appears logged out; log in before downloading images');","typeGuard":null,"tryCatchPattern":"try {\n  const saved = await cli.image({ prompt, outDir });\n} catch (e) {\n  if (e instanceof CommandExecutionError && e.message.startsWith('Failed to download grok image')) {\n    console.error('assets.grok.com blocked the download — log into grok.com in the automated tab and retry.');\n  } else throw e;\n}","preventionTips":["Always verify the automated grok.com tab is logged in before running image jobs.","Retry transient download failures with backoff — CDN 5xx is often momentary.","Download images promptly after generation; asset URLs can expire.","Avoid proxies/VPNs that Cloudflare may challenge."],"tags":["network","authentication","download","cloudflare"],"backgroundTag":"http-403-forbidden","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}