Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

With serverFunctions.components on, data server functions called during hydration never reach the network (frames intercept waits forever)

Aperta
#4,033 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
15/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
javascript, typescript

Direzione di ricerca

Start in packages/web/frames/src/client.ts, where the intercept passed to createServerComponentHandler (around line 1683) calls boundaryMayArrive() and awaitBoundary(id), then read the arrivals cache. Also read subFetch in packages/solid/src/client/hydration.ts and the tracing check from #4013. Reproduce by loading examples/room /live with components: true. Done means data server functions called during hydration reach the network and the summary leaves "summarizing…".

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

In an app with serverFunctions: { components: true }, a data server function (one that returns data, not a component) called during hydration never sends its request. The frames client's intercept parks the call waiting for a <solid-frame> boundary that a data function never has, and in two ways that wait never ends.

examples/room's /live page shows it on next (4937f0a):

  • Never connects: there are no /_server/live/* or /_server/data/summary requests at all, and no console errors.
  • UI stuck: the status pills stay at "connecting", presence shows "0 here" and "Not in the room yet", and the summary stays at "summarizing…".
  • Writes go one way: a message posted from one tab reaches the server but never shows in another tab.
  • Everywhere: it happens in dev over HTTP/1.1, in dev over HTTPS/HTTP/2, and in the production build, while _$HY.done === true.
  • Controls: room's / page, a live server component, works on the same server. The same /live source served with components: true removed connects, with both tabs in presence and posts crossing. examples/board doesn't set components: true, which is why it connects on the same build.

This is related to #3819, which uses the same page as its motivating case, but that issue is about the connection opening late. Here it never opens.

Cause

In packages/web/frames/src/client.ts, the intercept passed to createServerComponentHandler (around line 1683) runs for every server-function call, data functions included. While boundaryMayArrive() is true, meaning _$HY.done is unset or a fragment is pending, it treats a function with no boundary element as "a boundary that may still arrive" and returns awaitBoundary(id). That is a promise cached per function id in arrivals, and the call doesn't go to the network. A data function never gets a boundary, so it can only be released by the reveal hook. Two defects keep that release from ever happening.

1. The cached arrival promise can be a MockPromise that never resolves (confirmed)
  • The first call happens inside the hydration trace (subFetch in packages/solid/src/client/hydration.ts), which swaps the global Promise for MockPromise.
  • So new Promise(r => (resolve = r)) in awaitBoundary creates a MockPromise and resolve stays undefined.
  • In the browser, the arrivals entries for presence, transcript, roomCard and archive all had typeof resolve === "undefined", created exactly when Promise !== native.
  • The takeover calls after the root pass hit the same cached dead entry and hang.
  • If a reveal ever tries to release them, it throws TypeError: arrival.resolve is not a function. That throw was reproduced.

This is the same class of bug as #4013 (a lazy() loader promise made under hydration tracing). That fix added a tracing check, and frames doesn't consult it.

2. Waiters registered after the page's last reveal are never released (confirmed)

The summary source hangs even though its arrival was created with a real Promise:

  • Waiters are released only from a reveal notification, and only if hy.done && !hy.fr.pending() holds at that moment.
  • Timeline: reveals at about 520 ms and 720 ms, then the last one (the 4 s Archive panel) at about 4015 ms, with done still unset and pending() false.
  • _$HY.done = true is set about 5 ms later, from a setTimeout in drainHydrationCallbacks. So the last reveal kept the waiters, and no reveal comes after it.
  • Calls made by hydration-end recomputes (summary uses ssrSource: "client") register in that gap and wait forever.
  • Firing a synthetic reveal after done (with the dead MockPromise entries dropped first) immediately sent GET /_server/data/summary, and the summary started streaming.

A fresh call after hydration goes straight to the network, because boundaryMayArrive() is false once done is set. Only calls made in the hydration window are lost, and any components: true app that calls data server functions during hydration should hit this.

Possible fixes (untested)

  • Don't defer non-component functions in the intercept: a data function can never have a boundary.
  • Don't create or cache arrival promises while hydration tracing is on, as #4013's fix does for lazy().
  • Release outstanding waiters at hydration end (onHydrationEnd) as well as on reveals.

Regression?

Unknown. The intercept, awaitBoundary and boundaryMayArrive code predates the held-swap policy note (#2964) in the comments, and an older build (around 06c7717dd) behaves the same.

Lingua principale
TypeScript
Stelle
36.1k
Fork
1.1k
Merge medio
10h 42m
PR unite (30g)
361

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di solidjs/solid

Tutte le issue di solidjs/solid

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.