jackwener/OpenCLI · error · CommandExecutionError
Pixiv image download failed: ${result?.error || 'invalid dow
Error message
Pixiv image download failed: ${result?.error || 'invalid download result'} What it means
validateImageDownload verifies the result object returned by the image downloader: it must be an object with success === true, a positive safe-integer size, and the resolved URL/content type must match the expected file. If any of these fail, it throws CommandExecutionError 'Pixiv image download failed: <error or invalid download result>'. This catches failed, empty, or content-type-mismatched downloads before the plan is committed.
Source
Thrown at clis/pixiv/bookmark-download.js:84
...parsed,
filename: `${row.illust_id}_p${index}${parsed.extension}`,
};
});
const finalPath = path.join(outputRoot, 'illust', row.illust_id);
if (pixivPathEntryExists(finalPath)) {
throw new CommandExecutionError(`Refusing to overwrite existing Pixiv download: ${finalPath}`);
}
const createdDirs = [];
for (let cursor = path.dirname(finalPath); !fs.existsSync(cursor); cursor = path.dirname(cursor)) {
createdDirs.push(cursor);
if (path.dirname(cursor) === cursor) break;
}
return { kind: 'illust', illustId: row.illust_id, finalPath, files, createdDirs };
}
function validateImageDownload(result, file) {
if (!result || typeof result !== 'object' || result.success !== true || !Number.isSafeInteger(result.size) || result.size <= 0) {
throw new CommandExecutionError(`Pixiv image download failed: ${result?.error || 'invalid download result'}`);
}
const final = parsePixivImageUrl(result.finalUrl, 'Pixiv image download');
if (final.contentType !== file.contentType || result.contentType !== file.contentType) {
throw new CommandExecutionError(`Pixiv image download returned unexpected content type for ${file.filename}`);
}
}
async function commitIllustPlan(plan, cookies) {
const parent = path.dirname(plan.finalPath);
let staging;
try {
fs.mkdirSync(parent, { recursive: true });
staging = fs.mkdtempSync(path.join(parent, `.opencli-${plan.illustId}-`));
for (const file of plan.files) {
const destination = path.join(staging, file.filename);
const result = await httpDownload(file.url, destination, {
cookies,
headers: { Referer: 'https://www.pixiv.net/' },View on GitHub (pinned to 49907e53dc)
Solutions
- Read result.error from the thrown message to identify the actual failure (403/404/timeout etc.) and address that specific cause
- Ensure requests to i.pximg.net include the Referer: https://www.pixiv.net/ header — its absence commonly causes 403 download failures
- Refresh the Pixiv session/cookies and retry; CDN auth failures often stem from expired credentials
- Add a bounded retry with backoff around the download step for transient network errors
- Verify content-type/extension expectations; if Pixiv changed image formats, update parsePixivImageUrl handling
Example fix
// before
const result = await downloadImage(url, dest);
// after
async function downloadWithRetry(url, dest, attempts = 3) {
for (let i = 1; i <= attempts; i++) {
const result = await downloadImage(url, dest, { headers: { Referer: 'https://www.pixiv.net/' } });
if (result?.success === true && Number.isSafeInteger(result.size) && result.size > 0) return result;
if (i < attempts) await new Promise(r => setTimeout(r, 1000 * i));
}
throw new CommandExecutionError(`Pixiv image download failed after ${attempts} attempts`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate downloader contract expectations before committing the plan
function looksLikeValidDownload(result) {
return !!result && typeof result === 'object' && result.success === true
&& Number.isSafeInteger(result.size) && result.size > 0
&& typeof result.finalUrl === 'string' && result.finalUrl.length > 0;
} Type guard
function isValidImageDownload(result) {
return typeof result === 'object' && result !== null
&& result.success === true
&& Number.isSafeInteger(result.size) && result.size > 0
&& typeof result.finalUrl === 'string'
&& typeof result.contentType === 'string';
} Try / catch
try {
await commitIllustPlan(plan);
} catch (err) {
if (err instanceof CommandExecutionError && err.message.startsWith('Pixiv image download failed')) {
console.error(`download failed (${err.message}); will retry with backoff`);
await retryPlan(plan); // retry transient CDN/network failures
} else { throw err; }
} Prevention
- Always send Referer: https://www.pixiv.net/ when fetching i.pximg.net image URLs
- Keep the Pixiv session fresh; expired cookies cause CDN 403s
- Add bounded retry/backoff around individual image downloads for transient errors
- Check result.error in the message first — it names the underlying HTTP/network cause
- Verify disk space and permissions so downloads aren't truncated to size 0
When it happens
Trigger: The downloader returns {success:false,error:...} (HTTP error, network failure, Pixiv 403/404 on the image CDN), or returns success with a non-positive/missing size, or null/undefined result ('invalid download result'), called from commitIllustPlan.
Common situations: Image CDN rejects the request due to missing Referer headers or expired session; the original URL 404s after Pixiv CDN rotation; a rate-limit or timeout produces success:false; a proxy returns a tiny HTML error page recorded as size 0.
Related errors
- Failed to download grok image ${img.src}${reason}
- DOWNLOAD_ERROR
- 12306 queryByTrainNo returned HTTP ${resp.status}
- 12306 queryByTrainNo returned non-JSON body
- 12306 ${endpoint} returned non-JSON body
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ceeb84193efc8d1c.
Report an issue: GitHub.