{"record":{"id":"97297625b424436d","repo":"jackwener/OpenCLI","slug":"failed-to-download-pin-id-result-error-u","errorCode":null,"errorMessage":"Failed to download pin ${id}: ${result.error || 'unknown error'}","messagePattern":"Failed to download pin (.+?): (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/download.js","lineNumber":54,"sourceCode":"      throw new EmptyResultError('pinterest download', `pin \"${id}\" not found`);\n    }\n    const imageUrl = pickPinImage(pin.images);\n    if (!imageUrl) {\n      throw new CommandExecutionError(`Pin ${id} has no downloadable image (it may be a video or story pin)`);\n    }\n\n    fs.mkdirSync(output, { recursive: true });\n    const ext = path.extname(new URL(imageUrl).pathname) || '.jpg';\n    const destPath = path.join(output, `${id}${ext}`);\n\n    let result;\n    try {\n      result = await httpDownload(imageUrl, destPath, { timeout: 60000 });\n    } catch (err) {\n      throw new CommandExecutionError(`Failed to download pin ${id}: ${getErrorMessage(err)}`);\n    }\n    if (!result.success) {\n      throw new CommandExecutionError(`Failed to download pin ${id}: ${result.error || 'unknown error'}`);\n    }\n\n    return [{\n      pinId: id,\n      status: 'success',\n      size: formatBytes(result.size),\n      path: destPath,\n    }];\n  },\n});\n","sourceCodeStart":36,"sourceCodeEnd":65,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/download.js#L36-L65","documentation":"httpDownload completed without throwing but reported result.success === false; the command raises CommandExecutionError using result.error, or 'unknown error' if none was provided. This is an in-band download failure (e.g. non-2xx status, content mismatch) rather than an exception.","triggerScenarios":"Image server returning HTTP 403/404 for the CDN URL; expired or signed-URL mismatch; server returning an HTML error page instead of the image; result.error set by the downloader on bad status codes.","commonSituations":"Hotlink protection or geo-blocking on the image CDN; picking an old cached image URL that was purged; rate-limited requests after batch scraping.","solutions":["Re-resolve the pin to get a fresh image URL and retry — CDN URLs can expire.","Read result.error in the message for the specific HTTP status and address it.","Add delays/backoff between downloads to avoid rate limiting.","Retry with a different image rendition from pin.images if available."],"exampleFix":"// before\nawait cli.download(pinId); // stale image URL 403s\n// after\ntry { await cli.download(pinId); } catch (e) { const pin = await reFetch(pinId); await cli.download(pin.id); }","handlingStrategy":"retry","validationCode":"const head = await fetch(imageUrl, { method: 'HEAD' });\nif (!head.ok) console.warn(`image URL unhealthy: HTTP ${head.status}`);","typeGuard":"null","tryCatchPattern":"try {\n  await cli.download(pinId);\n} catch (e) {\n  if (/Failed to download pin/.test(e.message) && !/timed out/.test(e.message)) {\n    const pin = await refreshPin(pinId); // get fresh CDN URL\n    await cli.download(pin.id);\n  } else throw e;\n}","preventionTips":["Re-resolve pins to get fresh CDN URLs before retrying","Throttle batch downloads to avoid CDN rate limits","Read the embedded result.error for the HTTP status","Fall back to a different image rendition when one 403s"],"tags":["pinterest","http-error","download-failed","cdn"],"backgroundTag":"http-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}