jackwener/OpenCLI · error · CommandExecutionError
Pixiv image download did not create a valid file: ${file.fil
Error message
Pixiv image download did not create a valid file: ${file.filename} What it means
After a successful-looking download and validateImageDownload, commitIllustPlan lstats the staged file and requires it to be a real, non-symlink, non-empty file. This CommandExecutionError is thrown when the staged path is missing, a symlink, a directory, or zero bytes, meaning the downloader reported success but did not actually materialize the image. It is a post-download integrity guard.
Source
Thrown at clis/pixiv/bookmark-download.js:109
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/' },
timeout: 60000,
includeContentType: true,
});
validateImageDownload(result, file);
const stat = fs.lstatSync(destination);
if (stat.isSymbolicLink() || !stat.isFile() || stat.size <= 0) {
throw new CommandExecutionError(`Pixiv image download did not create a valid file: ${file.filename}`);
}
}
if (pixivPathEntryExists(plan.finalPath)) {
throw new CommandExecutionError(`Refusing to overwrite existing Pixiv download: ${plan.finalPath}`);
}
fs.renameSync(staging, plan.finalPath);
return plan.finalPath;
} catch (error) {
if (staging) {
try { fs.rmSync(staging, { recursive: true, force: true }); } catch {}
}
for (const directory of plan.createdDirs) {
try { fs.rmdirSync(directory); } catch {}
}
if (error instanceof CommandExecutionError) throw error;
throw new CommandExecutionError(`Pixiv illustration ${plan.illustId} download failed: ${error?.message || error}`);
}
}View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the download; transient empty responses are the most common cause
- Check free disk space and that the staging directory is writable
- Inspect the staging path for a symlink or directory and remove anything unexpected
- Verify the download command actually writes to the expected destination path (no cwd/path mismatch)
- Update the download tool/driver if zero-byte 'successful' downloads recur
Example fix
// before: trusting validateImageDownload alone
validateImageDownload(result, file);
// after: also fail fast on empty responses before committing
validateImageDownload(result, file);
if (result.size <= 0) throw new CommandExecutionError(`empty body for ${file.filename}`); Defensive patterns
Strategy: validation
Validate before calling
const stat = fs.lstatSync(destination, { throwIfNoEntry: false });
if (!stat || stat.isSymbolicLink() || !stat.isFile() || stat.size <= 0) {
throw new Error(`staged file invalid before commit: ${destination}`);
} Type guard
function isRegularNonEmptyFile(p) {
try {
const s = fs.lstatSync(p);
return s.isFile() && !s.isSymbolicLink() && s.size > 0;
} catch { return false; }
} Try / catch
try {
fs.lstatSync(destination);
} catch (err) {
if (err.code === 'ENOENT') {
console.warn(`Download produced no file for ${file.filename}; retrying`);
return retryDownload(file);
}
throw err;
} Prevention
- Always lstat the staged path before renaming into place
- Run downloads to a dedicated staging dir you control
- Monitor free disk space before large archives
- Alert on result.size <= 0 even when success === true
When it happens
Trigger: fs.lstatSync(destination) on the staging path returns a stat where stat.isSymbolicLink(), !stat.isFile(), or stat.size <= 0, right after validateImageDownload passed for file.filename.
Common situations: The download tool wrote to a different working directory than expected; a symlink-hijacking or disk issue replaced the file; the download command reported success but wrote 0 bytes on a flaky network or rate-limited response; antivirus/cleanup removed the staged file mid-run.
Related errors
- Refusing to overwrite existing Pixiv download: ${plan.finalP
- Pixiv illustration ${plan.illustId} download failed: ${error
- Pixiv image download returned unexpected content type for ${
- Suno download wrote no files for clip ${clip.id}
- Verify command returned no metric for baseline
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/68412e67aecdc834.
Report an issue: GitHub.