affaan-m/ECC · error · Error
pandoc did not produce a nonempty regular DOCX artifact
Error message
pandoc did not produce a nonempty regular DOCX artifact
What it means
After a nominally successful pandoc run, build() verifies the artifact: it lstat's the DOCX path and requires a regular, non-empty file. If pandoc reported success but produced nothing usable (zero-byte file, directory, missing file), this error is thrown, the stale/partial docx is removed, and ENOENT is remapped to the clearer 'pandoc did not produce a DOCX artifact' message.
Solutions
- Check the output directory after failure — confirm whether any DOCX exists and its size (ls -la out/).
- Run pandoc manually with the same command and inspect its output/exit code for silent filter failures.
- Free up disk space if the volume is full; a full disk commonly yields empty artifacts.
- Rerun in an isolated output directory to rule out concurrent processes deleting the artifact.
Example fix
// before $ pandoc md -o docx && echo ok # exit 0, but docx is 0 bytes // after $ df -h . # rule out disk-full $ pandoc md -o docx --verbose # surface silent filter failures $ node build-agreement.js --spec spec.json --out out # retry
Defensive patterns
Strategy: retry
Validate before calling
const fs = require('fs');
function verifyDocxArtifact(p) {
const st = fs.lstatSync(p); // throws ENOENT if missing
if (!st.isFile() || st.size === 0) throw new Error('DOCX artifact missing or empty');
}
verifyDocxArtifact(`${outDir}/${spec.file} MASTER.docx`); Type guard
null
Try / catch
try {
build(templatePath, specPath, outDir);
} catch (e) {
if (e.message.includes('DOCX artifact')) {
console.error('pandoc exited 0 but produced no usable DOCX; check filters and disk space');
} else throw e;
} Prevention
- Ensure adequate disk space before conversion; full disks commonly produce empty artifacts.
- Avoid pandoc filters that can fail silently while still exiting 0.
- Run builds in a dedicated output directory so concurrent cleanup jobs can't delete artifacts mid-run.
When it happens
Trigger: Pandoc exits 0 but writes to a different location, a zero-length .docx from a silently failing filter, or something (another process/cleanup hook) deleting the file between conversion and the lstat check.
Common situations: Flaky/silently failing pandoc filters or Lua filters; disk-full conditions yielding truncated/empty output; racing background jobs cleaning the output directory mid-build.
Related errors
- all overlays must be readable local files
- all takes must be readable local files
- artifact byte count exceeded during reading
- artifact byte count mismatch
- artifact changed before reading
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/bc3b75e3b3f625c9.
Report an issue: GitHub.
Appendix: source
Thrown at skills/master-agreement-generator/scripts/build-agreement.js:188
// beside a newly built Markdown draft, including explicit Markdown-only builds.
fs.rmSync(docxPath, { force: true });
const result = { markdown: mdPath, docx: null, docxSkipped: false, documentStatus: 'draft' };
if (options.markdownOnly === true) {
result.docxSkipped = true;
return result;
}
const canConvert = options.pandoc === undefined ? pandocAvailable() : options.pandoc;
if (!canConvert) {
throw new Error('DOCX required: pandoc unavailable; use --markdown-only for an explicit Markdown-only draft');
}
try {
const converted = spawnSync('pandoc', [mdPath, '-o', docxPath], CONVERTER_OPTIONS);
if (converted.error || converted.status !== 0) {
throw new Error('pandoc conversion failed; DOCX unavailable');
}
const artifact = fs.lstatSync(docxPath);
if (!artifact.isFile() || artifact.size === 0) {
throw new Error('pandoc did not produce a nonempty regular DOCX artifact');
}
} catch (error) {
fs.rmSync(docxPath, { force: true });
if (error.code === 'ENOENT') throw new Error('pandoc did not produce a DOCX artifact');
throw error;
}
result.docx = docxPath;
return result;
}
function main(argv) {
const [templatePath, specPath, outDir, ...flags] = argv;
if (!templatePath || !specPath || !outDir ||
flags.some(flag => !['--require-docx', '--markdown-only'].includes(flag)) ||
flags.length > 1) {
console.error('usage: build-agreement.js <template.md> <spec.json> <out_dir> [--require-docx | --markdown-only]');
return 2;
}View on GitHub (pinned to 8321021c54)