Skip to content

Commit 544f3a1

Browse files
rsbhclaude
andauthored
fix: add custom error handler and fix hydration errors (#88)
Nitro + Vite 8 dev mode doesn't properly serialize HTTPError across the module runner boundary, causing Parse Error on all 404 API responses. Custom error handler catches errors inside the runner and returns proper JSON responses. Also fixes nested <p> hydration error when MDX content contains raw HTML <p> tags, and skips prefetching for URLs with file extensions. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7b44d3e commit 544f3a1

4 files changed

Lines changed: 19 additions & 2 deletions

File tree

packages/chronicle/src/components/mdx/paragraph.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Children, isValidElement, type ComponentProps } from 'react'
22
import styles from './paragraph.module.css'
33

4-
const BLOCK_ELEMENTS = new Set(['summary', 'details', 'div', 'table', 'ul', 'ol'])
4+
const BLOCK_ELEMENTS = new Set(['summary', 'details', 'div', 'table', 'ul', 'ol', 'p'])
55

66
function hasBlockChild(children: React.ReactNode): boolean {
77
return Children.toArray(children).some(

packages/chronicle/src/lib/preload.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ function isApisRoute(pathname: string): boolean {
2828
return pathname === '/apis' || pathname.startsWith('/apis/');
2929
}
3030

31+
function hasFileExtension(pathname: string): boolean {
32+
const lastSegment = pathname.split('/').pop() ?? '';
33+
return lastSegment.includes('.');
34+
}
35+
3136
export function prefetchPageData(pathname: string) {
32-
if (isApisRoute(pathname)) return;
37+
if (isApisRoute(pathname) || hasFileExtension(pathname)) return;
3338
queryClient.prefetchQuery({
3439
queryKey: pageDataQueryKey(pathname),
3540
queryFn: () => fetchPageDataByPathname(pathname),
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { defineErrorHandler, HTTPError } from 'nitro';
2+
3+
export default defineErrorHandler((error, _event) => {
4+
const status = HTTPError.isError(error) ? error.status : 500;
5+
const message = error.message || 'Internal Server Error';
6+
7+
return new Response(JSON.stringify({ error: true, status, message }), {
8+
status,
9+
headers: { 'Content-Type': 'application/json' },
10+
});
11+
});

packages/chronicle/src/server/vite-config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export async function createViteConfig(
145145
},
146146
nitro: {
147147
logLevel: 2,
148+
errorHandler: path.resolve(packageRoot, 'src/server/error.ts'),
148149
publicAssets: [{ dir: path.resolve(projectRoot, 'public') }],
149150
output: {
150151
dir: resolveOutputDir(projectRoot, preset),

0 commit comments

Comments
 (0)