@fedify/nuxt and @fedify/solidstart defer Fedify's 406 Not Acceptable response so the application can serve another representation. Both can lose that response and send 404 when the application has no representation to serve.
Nuxt
The middleware records a deferred 406 in the H3 event context, and the plugin tries to restore it in Nitro's beforeResponse hook. On a route miss, Nitro's default error handler sends the 404 directly. The hook is never called, so the deferred response is lost.
To reproduce, use createFedifyMiddleware() and the Fedify plugin with a preemptive H3 router and Nitro's default error handler. Make Fedify reject /users/alice through onNotAcceptable, leave that path unmatched in the router, and request it with Accept: image/png. The response is 404 instead of 406, and the beforeResponse hook does not run.
The plugin also skips the fallback whenever event.context.matchedRoute is set. A catch-all renderer that returns 404 therefore also produces 404 instead of 406. A fix needs to distinguish a renderer's missing-page result from an application route's deliberate 404.
SolidStart
onBeforeResponse() checks event.response.status, then removes the stored 406. When a handler returns a Web Response, SolidStart calls the hook before H3 applies that response's status. A returned Response with status 404 can therefore look like status 200 to the hook, which discards the fallback.
With fedifyMiddleware() installed, register a Fedify actor dispatcher for /users/{identifier} and make the application handler return:
return new Response("No HTML representation", { status: 404 });
Request /users/alice with Accept: image/png. The final response is 404 instead of 406. Returning no response or throwing a 404 also loses the fallback in the tested pipeline. Setting the event's response status to 404 before returning a body does produce the expected 406, so the result depends on how the handler expresses the same status.
Affected branches and verification
The oldest affected 2.x branch for both packages is 2.2-maintenance, verified at 421e819. Neither package exists on 2.0-maintenance or 2.1-maintenance. The failures also reproduce on the fetched tips of 2.3-maintenance and 2.4-maintenance.
The reproductions ran unchanged adapter sources, with Federation.fetch() selecting onNotAcceptable to isolate the fallback. Nuxt's runtime middleware and plugin were tested with H3 1.15.3 and Nitro 2.13.3's default error handler. SolidStart was tested through its actual createMiddleware() wrapper in version 1.3.2. The lifecycle reproductions showed the failures under Bun 1.2.22; the Nuxt error path was also reproduced under Deno 2.9.7. The host was Fedora Linux 44 (x86_64). Full Nuxt and SolidStart applications were not built.
The regression coverage should include the route-miss error path and a returned Response(404), while preserving successful application responses. The SolidStart handler tests associated with #873 set the event's status directly and do not cover the returned-response timing.
@fedify/nuxtand@fedify/solidstartdefer Fedify's406 Not Acceptableresponse so the application can serve another representation. Both can lose that response and send 404 when the application has no representation to serve.Nuxt
The middleware records a deferred 406 in the H3 event context, and the plugin tries to restore it in Nitro's
beforeResponsehook. On a route miss, Nitro's default error handler sends the 404 directly. The hook is never called, so the deferred response is lost.To reproduce, use
createFedifyMiddleware()and the Fedify plugin with a preemptive H3 router and Nitro's default error handler. Make Fedify reject/users/alicethroughonNotAcceptable, leave that path unmatched in the router, and request it withAccept: image/png. The response is 404 instead of 406, and thebeforeResponsehook does not run.The plugin also skips the fallback whenever
event.context.matchedRouteis set. A catch-all renderer that returns 404 therefore also produces 404 instead of 406. A fix needs to distinguish a renderer's missing-page result from an application route's deliberate 404.SolidStart
onBeforeResponse()checksevent.response.status, then removes the stored 406. When a handler returns a WebResponse, SolidStart calls the hook before H3 applies that response's status. A returnedResponsewith status 404 can therefore look like status 200 to the hook, which discards the fallback.With
fedifyMiddleware()installed, register a Fedify actor dispatcher for/users/{identifier}and make the application handler return:Request
/users/alicewithAccept: image/png. The final response is 404 instead of 406. Returning no response or throwing a 404 also loses the fallback in the tested pipeline. Setting the event's response status to 404 before returning a body does produce the expected 406, so the result depends on how the handler expresses the same status.Affected branches and verification
The oldest affected 2.x branch for both packages is
2.2-maintenance, verified at 421e819. Neither package exists on2.0-maintenanceor2.1-maintenance. The failures also reproduce on the fetched tips of2.3-maintenanceand2.4-maintenance.The reproductions ran unchanged adapter sources, with
Federation.fetch()selectingonNotAcceptableto isolate the fallback. Nuxt's runtime middleware and plugin were tested with H3 1.15.3 and Nitro 2.13.3's default error handler. SolidStart was tested through its actualcreateMiddleware()wrapper in version 1.3.2. The lifecycle reproductions showed the failures under Bun 1.2.22; the Nuxt error path was also reproduced under Deno 2.9.7. The host was Fedora Linux 44 (x86_64). Full Nuxt and SolidStart applications were not built.The regression coverage should include the route-miss error path and a returned
Response(404), while preserving successful application responses. The SolidStart handler tests associated with #873 set the event's status directly and do not cover the returned-response timing.