{"record":{"id":"1dfc9a6faae046f2","repo":"garrytan/gstack","slug":"input-file-not-found-input","errorCode":null,"errorMessage":"input file not found: ${input}","messagePattern":"input file not found: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"make-pdf/src/orchestrator.ts","lineNumber":84,"sourceCode":"    const total = ((Date.now() - this.totalStart) / 1000).toFixed(1);\n    process.stderr.write(`\\r\\x1b[KDone in ${total}s. ${extra}\\n`);\n  }\n  fail(stage: string, err: Error): void {\n    if (!this.quiet) process.stderr.write(\"\\r\\x1b[K\");\n    // Always emit failure info, even in quiet mode — this is an error path.\n    process.stderr.write(`${stage} failed: ${err.message}\\n`);\n  }\n}\n\n/**\n * generate — full pipeline. Returns the output PDF path on success.\n */\nexport async function generate(opts: GenerateOptions): Promise<string> {\n  const progress = new ProgressReporter(opts);\n  const input = path.resolve(opts.input);\n\n  if (!fs.existsSync(input)) {\n    throw new Error(`input file not found: ${input}`);\n  }\n\n  const to = opts.to ?? \"pdf\";\n  const outputPath = path.resolve(\n    opts.output ?? path.join(os.tmpdir(), `${deriveSlug(input)}.${to}`),\n  );\n\n  // Stage 1: read markdown\n  progress.begin(\"Reading markdown\");\n  const markdown = fs.readFileSync(input, \"utf8\");\n  progress.end(\"Reading markdown\");\n\n  // Stage 1.5: diagram pre-pass — extract ```mermaid/```excalidraw fences and\n  // swap in placeholder tokens. Rendering happens after the tab opens below.\n  const extraction = extractDiagramFences(markdown);\n\n  // Stage 2: render HTML\n  progress.begin(\"Rendering HTML\");","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/make-pdf/src/orchestrator.ts#L66-L102","documentation":"Thrown by generate() (the full PDF pipeline) when the resolved input markdown file does not exist. The input is resolved to an absolute path first, so the message shows the full path that was checked. This is an early validation guard before any rendering work begins.","triggerScenarios":"Calling generate({input}) where path.resolve(opts.input) does not exist on disk. A typo in the filename, a relative path resolved against an unexpected CWD, a glob passed instead of a file, or a file that was deleted between the CLI parse and the run.","commonSituations":"Typo in the CLI argument (`pdf reprot.md`); CWD mismatch (running from a different directory than the markdown); a shell glob the shell did not expand; a build step that moved/deleted the input; a path with spaces needing quotes.","solutions":["Verify the file exists at the absolute path printed in the message.","Pass an absolute path or run from the directory containing the markdown.","Quote paths containing spaces.","If using a glob, expand it in the shell or pass a single resolved file."],"exampleFix":"# before\n$ pdf --strict reprot.md   # typo\nError: input file not found: /cwd/reprot.md\n\n# after\n$ pdf --strict report.md","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\nimport path from 'node:path';\n\nfunction validateInput(input: string): string {\n  const abs = path.resolve(input);\n  if (!fs.existsSync(abs)) throw new Error(`input file not found: ${abs}`);\n  if (!fs.statSync(abs).isFile()) throw new Error(`input is not a file: ${abs}`);\n  return abs;\n}\n\nconst input = validateInput(opts.input);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass an absolute input path in CI to avoid CWD ambiguity.","Quote paths containing spaces.","Expand shell globs before passing to make-pdf.","Verify the file exists in the build step before invoking generate()."],"tags":["make-pdf","input","filesystem","validation"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}