{"record":{"id":"0cfcf25b78252e5a","repo":"affaan-m/ECC","slug":"docx-required-pandoc-unavailable-use-markdown-only-for-an","errorCode":null,"errorMessage":"DOCX required: pandoc unavailable; use --markdown-only for an explicit Markdown-only draft","messagePattern":"DOCX required: pandoc unavailable; use --markdown-only for an explicit Markdown-only draft","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/master-agreement-generator/scripts/build-agreement.js","lineNumber":179,"sourceCode":"function build(templatePath, specPath, outDir, options = {}) {\n  const template = fs.readFileSync(templatePath, 'utf8');\n  const spec = JSON.parse(fs.readFileSync(specPath, 'utf8'));\n  const markdown = render(template, spec, options.now);\n  const { root, mdPath, docxPath } = outputPaths(outDir, spec.file);\n  fs.mkdirSync(root, { recursive: true });\n  fs.writeFileSync(mdPath, markdown, 'utf8');\n\n  // Generated DOCX is replaceable output. Never leave a stale or partial copy\n  // beside a newly built Markdown draft, including explicit Markdown-only builds.\n  fs.rmSync(docxPath, { force: true });\n  const result = { markdown: mdPath, docx: null, docxSkipped: false, documentStatus: 'draft' };\n  if (options.markdownOnly === true) {\n    result.docxSkipped = true;\n    return result;\n  }\n  const canConvert = options.pandoc === undefined ? pandocAvailable() : options.pandoc;\n  if (!canConvert) {\n    throw new Error('DOCX required: pandoc unavailable; use --markdown-only for an explicit Markdown-only draft');\n  }\n  try {\n    const converted = spawnSync('pandoc', [mdPath, '-o', docxPath], CONVERTER_OPTIONS);\n    if (converted.error || converted.status !== 0) {\n      throw new Error('pandoc conversion failed; DOCX unavailable');\n    }\n    const artifact = fs.lstatSync(docxPath);\n    if (!artifact.isFile() || artifact.size === 0) {\n      throw new Error('pandoc did not produce a nonempty regular DOCX artifact');\n    }\n  } catch (error) {\n    fs.rmSync(docxPath, { force: true });\n    if (error.code === 'ENOENT') throw new Error('pandoc did not produce a DOCX artifact');\n    throw error;\n  }\n  result.docx = docxPath;\n  return result;\n}","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/master-agreement-generator/scripts/build-agreement.js#L161-L197","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnode build-agreement.js --spec spec.json --out out   # pandoc missing -> throws\n// after\nbrew install pandoc           # or: apt-get install -y pandoc\nnode build-agreement.js --spec spec.json --out out\n# or, if DOCX not needed:\nnode build-agreement.js --spec spec.json --out out --markdown-only","handlingStrategy":"fallback","validationCode":"const { spawnSync } = require('child_process');\nconst hasPandoc = spawnSync('pandoc', ['--version']).status === 0;\nif (!hasPandoc && requireDocx) throw new Error('pandoc must be installed');","typeGuard":"null","tryCatchPattern":"try {\n  build(templatePath, specPath, outDir);\n} catch (e) {\n  if (e.message.includes('pandoc unavailable')) {\n    console.error('Install pandoc, or rerun with --markdown-only if DOCX is optional');\n  } else throw e;\n}","preventionTips":["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."],"tags":["pandoc","dependency","cli"],"backgroundTag":"command-not-found","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}