affaan-m/ECC · error · Error
DOCX required: pandoc unavailable; use --markdown-only for…
Error message
DOCX required: pandoc unavailable; use --markdown-only for an explicit Markdown-only draft
What it means
After writing the Markdown draft, build() converts it to DOCX with pandoc. If DOCX conversion is requested (the default) and pandoc is not available on PATH (or options.pandoc resolves to false) without --markdown-only, it throws this error directing the user to the explicit markdown-only escape hatch. The library treats DOCX as required unless the user explicitly opts out.
Solutions
- Install pandoc (e.g. brew install pandoc, apt-get install pandoc, choco install pandoc) and confirm with `pandoc --version`.
- If DOCX genuinely isn't needed, pass --markdown-only on the CLI (or { markdownOnly: true } programmatically) to explicitly skip conversion.
- Verify pandoc is on PATH for the environment running the script (CI containers may differ from your shell).
- Prefer an explicit install over disabling conversion — the error is deliberately worded to force a conscious choice.
Example fix
// before node build-agreement.js --spec spec.json --out out # pandoc missing -> throws // after brew install pandoc # or: apt-get install -y pandoc node build-agreement.js --spec spec.json --out out # or, if DOCX not needed: node build-agreement.js --spec spec.json --out out --markdown-only
Defensive patterns
Strategy: fallback
Validate before calling
const { spawnSync } = require('child_process');
const hasPandoc = spawnSync('pandoc', ['--version']).status === 0;
if (!hasPandoc && requireDocx) throw new Error('pandoc must be installed'); Type guard
null
Try / catch
try {
build(templatePath, specPath, outDir);
} catch (e) {
if (e.message.includes('pandoc unavailable')) {
console.error('Install pandoc, or rerun with --markdown-only if DOCX is optional');
} else throw e;
} Prevention
- Provision pandoc in your dev image/CI (apt-get install -y pandoc or equivalent) so conversion always works.
- Only pass --markdown-only when DOCX truly isn't needed — it's an explicit opt-out, not a workaround.
- Verify pandoc presence in CI as a pre-flight step before running the build.
When it happens
Trigger: Running the script without --markdown-only on a machine where pandoc is not installed or not on PATH; running in a minimal container/CI image lacking pandoc; options.pandoc=false passed programmatically without markdownOnly:true.
Common situations: Fresh dev machine or Docker image without pandoc; Windows CI runners where pandoc isn't preinstalled; calling build() from another Node script and forgetting to set options.markdownOnly.
Related errors
- Agents directory not found
- --all-harnesses and --harness are mutually exclusive.
- all overlays must be readable local files
- all takes must be readable local files
- AMBIGUOUS_PLUGIN_SCOPES
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/0cfcf25b78252e5a.
Report an issue: GitHub.
Appendix: source
Thrown at skills/master-agreement-generator/scripts/build-agreement.js:179
function build(templatePath, specPath, outDir, options = {}) {
const template = fs.readFileSync(templatePath, 'utf8');
const spec = JSON.parse(fs.readFileSync(specPath, 'utf8'));
const markdown = render(template, spec, options.now);
const { root, mdPath, docxPath } = outputPaths(outDir, spec.file);
fs.mkdirSync(root, { recursive: true });
fs.writeFileSync(mdPath, markdown, 'utf8');
// Generated DOCX is replaceable output. Never leave a stale or partial copy
// 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;
}View on GitHub (pinned to 8321021c54)