Astro Info
Astro v7.0.0-beta.4
Node v24.16.0
System Linux (x64)
Output server
Adapter @astrojs/node
(Built from main at 4c4a91c3, so this includes #17041. The version still prints 7.0.0-beta.4 because that's the last release.)
Describe the Bug
Follow-up to #17041 (now merged), where I flagged this as out of scope.
On the composable path, if you wire the pipeline up yourself with app.use(middleware()) and app.use(pages()), an error thrown from your own src/middleware.ts never becomes 500.astro. It falls through to Hono, which answers with its default plain-text Internal Server Error.
The all-in-one astro() handler doesn't have this problem (the same throw renders 500.astro there), so it's specific to wiring middleware() up on its own. With #17041 in place you can watch both sides on one server: a page that throws during render now gets 500.astro, but a middleware throw still falls through to Hono.
As far as I can tell it's the same shape as #16952. AstroHandler.render() wraps the whole middleware and page chain in a try/catch and renders 500.astro when something throws, but the composable middleware() just hands off to AstroMiddleware.handle() / callMiddleware() with nothing around it. The fallback from #17041 only sits on the pages() side.
What's the expected result?
A throw in src/middleware.ts should render 500.astro, the same way astro() and the normal adapter path already do.
Link to Minimal Reproducible Example
https://github.com/iseraph-dev/astro-hono-middleware-500
/boom throws in middleware and /page-throws throws during render. Build it, run node ./dist/server/entry.mjs, then hit both: /page-throws gives you 500.astro, /boom gives you Hono's plain text.
Possible fix
A try/catch straight inside middleware() doesn't really work, since its next is the host's next and it would also catch errors from Hono middleware further down the chain, hiding them from the user's own app.onError. Something opt-in exported from astro/hono would fit better, maybe an onError() you hand to Hono (app.onError(onError())), so Astro's error rendering plugs into Hono's error hook only when you want it. Happy to open a PR if that sounds right.
Participation
Astro Info
(Built from
mainat4c4a91c3, so this includes #17041. The version still prints7.0.0-beta.4because that's the last release.)Describe the Bug
Follow-up to #17041 (now merged), where I flagged this as out of scope.
On the composable path, if you wire the pipeline up yourself with
app.use(middleware())andapp.use(pages()), an error thrown from your ownsrc/middleware.tsnever becomes500.astro. It falls through to Hono, which answers with its default plain-textInternal Server Error.The all-in-one
astro()handler doesn't have this problem (the same throw renders500.astrothere), so it's specific to wiringmiddleware()up on its own. With #17041 in place you can watch both sides on one server: a page that throws during render now gets500.astro, but a middleware throw still falls through to Hono.As far as I can tell it's the same shape as #16952.
AstroHandler.render()wraps the whole middleware and page chain in a try/catch and renders500.astrowhen something throws, but the composablemiddleware()just hands off toAstroMiddleware.handle()/callMiddleware()with nothing around it. The fallback from #17041 only sits on thepages()side.What's the expected result?
A throw in
src/middleware.tsshould render500.astro, the same wayastro()and the normal adapter path already do.Link to Minimal Reproducible Example
https://github.com/iseraph-dev/astro-hono-middleware-500
/boomthrows in middleware and/page-throwsthrows during render. Build it, runnode ./dist/server/entry.mjs, then hit both:/page-throwsgives you500.astro,/boomgives you Hono's plain text.Possible fix
A try/catch straight inside
middleware()doesn't really work, since itsnextis the host'snextand it would also catch errors from Hono middleware further down the chain, hiding them from the user's ownapp.onError. Something opt-in exported fromastro/honowould fit better, maybe anonError()you hand to Hono (app.onError(onError())), so Astro's error rendering plugs into Hono's error hook only when you want it. Happy to open a PR if that sounds right.Participation