[Bug?]: Cannot set headers after they are sent to the client
Duplicates
- [x] I have searched the existing issues
Latest version
- [x] I have tested the latest version
Current behavior 😯
I'm trying to use query() with createAsync() in one of my page. Like the following,
// routes/(baseLayout)/index.tsx
import { createAsync, query, redirect, RouteDefinition } from "@solidjs/router";
import { Dialog } from "~/components/Dialog";
const getQuote = query(async () => {
const quote = await fetch("https://zenquotes.io/api/random");
throw redirect("/auth/signin");
}, "posts");
function DialogTrigger() {
return <div>Open dialog</div>;
}
export const route = {
info: {
breadcrumbs: {
label: "Home",
path: "/",
},
},
} satisfies RouteDefinition;
export default function Home() {
const quote = createAsync(() => getQuote());
return (
<div>
{JSON.stringify(quote())}
<Dialog trigger={DialogTrigger} />
</div>
);
}
But when i go to the page i got the following error:
I tried to refresh the page over and over again, but no hope. Seems like this will occurred when we have fetch() and redirect() altogether. I've tried to change the query() code with just fetch() or redirect() and it's working as expected.
Expected behavior 🤔
No error occurred.
Steps to reproduce 🕹
Steps:
- Create
query()withfetch()andredirect() - Go to the corresponding page
- The error will appeared.
Context 🔦
No response
Your environment 🌎
System:
- OS: macOS Tahoe 26.0
- CPU: Apple M3
Binaries:
- Node: v22.15.0
npmPackages:
- "@solidjs/router": "^0.15.4",
- "@solidjs/start": "^1.2.0",
- "solid-js": "^1.9.10",
- "vinxi": "^0.5.8"
I faced this issue before and found this somewhat helpful post https://www.answeroverflow.com/m/1256901524974604308.
Basically add {deferStream: true} as second parameter to createAsync().
Here is what is happening
- The html starts streaming to the client before
getQuote()finishes. - Then the redirect is thrown which is done via 302 redirect which sets the location header. This is why the error is complaining about headers, because the headers were already sent with the initial streamed response.
- Adding
{deferStream: true}will defer sending a response until aftergetQuote()finishes so there will only be one response instead of an initial and a second response with the result ofgetQuote().
My understanding is somewhat shaky so the details might not be 100%. For some reason when I just tried to reproduce the error, the response was always deferred so I never got the error 🤷
@brenelz close? this issue can never be fixed without deferStream. this is the nature of streaming
Perhaps need to update the Docs as well. Initially i encounter this issue because following the auth guide in the Docs.
https://docs.solidjs.com/solid-start/advanced/auth#protected-routes
So this can be closed?
Headers can only be sent before the response body, that's how the HTTP protocol works. If the body(of any file) started streaming already, then headers cannot longer be sent. I suppose we can close this @brenelz