-
-
Notifications
You must be signed in to change notification settings - Fork 101
Improve error handling across build pipeline #414
Description
Problem
When vocs build fails, it's extremely difficult to diagnose what went wrong. Errors are either silently swallowed, missing file path / line context, or immediately kill the process while discarding diagnostic info that Vite/Rollup already has.
This makes debugging build failures a trial-and-error process of commenting out pages until the broken one is found.
Current behavior
1. src/vite/build.ts: Prerender and scripts phases silently swallow errors
The catch blocks at lines ~59-61 (prerender) and ~82-84 (scripts) call the lifecycle hook but do not re-throw. When used without CLI hooks (e.g. programmatic API), the build silently continues after failure:
// prerender phase: error is caught but never re-thrown
catch (error) {
hooks?.onPrerenderEnd?.({ error: error as Error })
// ← build continues as if nothing happened
}Same pattern for the scripts phase.
2. src/vite/prerender.tsx: No per-route error handling
The prerender loop has no try/catch per route. If a single page fails to render, the entire prerender aborts with no indication of which route caused the failure:
for (const route of routes) {
const body = await mod.prerender(route) // ← one bad page kills everything
// ...
}3. src/cli/commands/build.ts: Error details are discarded
The CLI hooks only print error.message and immediately process.exit(1), discarding the stack trace, source file path, and line/column info that Vite/Rollup errors carry:
onBundleEnd({ error }) {
if (error) {
spinner.client.fail(`bundles failed to build: ${error.message}`)
process.exit(1) // ← error.id, error.loc, error.frame, error.stack all lost
}
}Vite/Rollup errors typically include error.id (file path), error.loc (line/column), error.frame (code snippet), and error.plugin, none of which are surfaced.
4. src/vite/plugins/mdx.ts: No error wrapping around MDX compilation
The @mdx-js/rollup plugin is passed through with zero wrapping. MDX syntax errors (unclosed tags, invalid JSX, bad frontmatter) produce errors from micromark with file: '' (empty string), so the source file path is lost entirely. The error shape looks like:
{
line: 28,
column: 2,
file: '', // ← empty, useless
reason: 'Unexpected end of file before name...',
source: 'micromark-extension-mdx-jsx',
ruleId: 'unexpected-eof'
}
The file path is available in the Rollup transform hook's id parameter but is never attached to the error.
5. src/vite/plugins/dev.tsx: Dev server SSR middleware has no catch block
The try { ... } finally { next() } pattern means SSR render errors crash the dev server instead of showing Vite's error overlay. Related: #163.
Expected behavior
- Build errors should include the file path, line/column (when available), and a readable error message
- Prerender/scripts phase errors should not be silently swallowed
- Dev server should show an error overlay instead of crashing
- The CLI should print Vite/Rollup error properties (
error.id,error.loc,error.frame) when available
Reproduction
- Create any MDX page with a syntax error, e.g. a lone
<on a line:# Test page Some content < - Run
vocs build - Output shows a huge output, too generic and not understandable by both human and AI scan
- The only way to find the broken file is to binary-search by removing pages and retest the build
Environment
- vocs: 1.2.2 (also verified against 1.4.1 source - same issues exist)
I'm happy to submit a PR addressing these.