[2.0 rc.14 / next] SSR: a rejection contained by `<Errored>` is still an unhandled rejection when an async sibling shares its children slot (exits Node)
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 66/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- nodejs, typescript
- Ambito
- frontend
Direzione di ricerca
L'errore viene lanciato in createErrorBoundary in packages/solid/src/server/signals.ts, dove viene creato il Promise.all(pending.p) combinato e lanciato come NotReadyError. Inizia da lì e verifica perché nulla attende quella promise una volta che il fratello mantiene lo slot in pending. Esegui la riproduzione dell'issue, che dovrebbe mostrare Error: boom come rejection non gestita. È completato quando non viene segnalata alcuna rejection non gestita e l'output HTML resta invariato, con il fallback Errored ancora renderizzato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
During renderToStream, an async read that rejects under <Errored> is contained (the fallback renders), but the rejection is also left unhandled when the boundary shares a {props.children} slot with an async sibling. Node's default --unhandled-rejections=throw then ends the process. Another <Errored> around the whole tree does not help: the error is not escaping the render, it is an internal promise nobody handles.
Reproduction
import { renderToStream } from "@solidjs/web";
import { createMemo, Errored, Loading } from "solid-js";
import type { ParentProps } from "solid-js";
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
process.on("unhandledRejection", (reason) => console.log("unhandled:", String(reason)));
function Layout(props: ParentProps) {
return <main>{props.children}</main>;
}
function Fails() {
const value = createMemo(async () => {
await delay(5);
throw new Error("boom");
});
return <p>{value()}</p>;
}
function Later() {
const value = createMemo(async () => {
await delay(20);
return "later";
});
return <p>{value()}</p>;
}
renderToStream(() => (
<Loading fallback={<p>loading</p>}>
<Layout>
<Errored fallback={(_error) => <p>failed</p>}>
<Fails />
</Errored>
<Later />
</Layout>
</Loading>
)).then((html) => console.log(html));
| HTML | unhandledRejection |
|
|---|---|---|
| as above | <main><p>failed</p><p>later</p></main> |
Error: boom |
wrapped in another <Errored> |
same | Error: boom |
<Later /> removed |
<main><p>failed</p></main> |
none |
<Later /> after </Layout> |
<main><p>failed</p></main><p>later</p> |
none |
no <Layout> (both directly in <Loading>) |
<p>failed</p><p>later</p> |
none |
Without the handler, Node exits. Reproduces on 2.0.0-rc.14, also with #3936 applied; the code below is unchanged on next.
Cause
The server boundary's resolve (packages/solid/src/server/signals.ts, createErrorBoundary) throws a combined promise while its holes are pending:
const all: any = Promise.all(pending.p);
if (pending.p.some(p => (p as any).$clientHole)) all.$clientHole = true;
throw new NotReadyError(all);
When the sibling keeps the slot pending and the slot is retried, nothing awaits that all any more, so its rejection is reported even though the boundary handled the error and rendered its fallback.
Expected
A rejection that <Errored> contains is handled, as for a rejecting direct child of <Loading> (#3570, #3594) and in the browser (#3769).
Possible fix
Mark the combined promise handled where it is created; whoever awaits it still sees the rejection:
const all: any = Promise.all(pending.p);
all.catch(() => {});
With that line in rc.14's dist/server.dev.js, the reproduction reports no unhandled rejection and renders the same HTML.
(submitted by Claude Opus 5.5 on behalf of rvlzzr)
- Lingua principale
- TypeScript
- Stelle
- 36.1k
- Fork
- 1.1k
- Merge medio
- 9h 56m
- PR unite (30g)
- 336
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di solidjs/solid
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 12/100
solidjs/solid#3975 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 Mezza giornata Idoneità per principianti 32/100
solidjs/solid#3974 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 52/100
I maintainer di solito rispondono entro 1 giorno
-
hydrate() run mid-parse leaves dead server nodes beside fresh client copies (async entry script)Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 20/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di solidjs/solid
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: [A11y] Missing accessible name on icon-only standalone links (WCAG 2.1 SC 2.4.4, 4.1.2)Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
jaegertracing/jaeger-ui#4596 ·
I maintainer di solito rispondono entro 1 giorno
-
area:tui enhancement platform:macos
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
anthropics/claude-code#101490 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
netlify/netlify-mcp#75 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno