You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The startup CI stage (test_startup.sh) only asserts that the server boots — it greps the startup output for NiceGUI ready to go and the absence of Traceback|Error, but it never issues an HTTP request. So any regression that is latent until a request slips straight through.
#6061 is the concrete case: #5960 set Storage.path = None at import time (clobbered transitively via the docs' from nicegui.testing import ...). The server boots fine; the crash — TypeError: unsupported operand type(s) for /: 'NoneType' and 'str' in _create_user_storage → Storage.path / f'storage-{id}.json' — only fires on the first storage-touching request. With no client connecting during the startup job's window, that code path is never exercised, so the job stays green.
Evidence
All full-test / {3.10–3.14} / startup jobs passed on the #5960 merge commit 5328b594; the regression was reported by a user (#6061), not caught by CI.
Empirical repro + CI timings
Run main.py on 0a1e6597 (reapplied Randomize test ports/dirs for parallel pytest sessions #5960, pre-fix) and issue one request to any page that uses app.storage.user → 500 with the NoneType / str traceback. The traceback travels the HTTP request path (uvicorn → _create_user_storage), so a single request during the startup window would have tripped the existing grep -qE "Traceback|Error" in test_startup.sh. CI simply never sends one.
Job durations on that run: startup ≈ 10 min, pytest ≈ 21 min (per Python version, n=5). The merge gate is bound by the ~21 min pytest job, and the startup job finishes ~11 min earlier.
Proposed fix
After NiceGUI ready to go, have test_startup.sh hit the running server with at least one real request — the main website and each example — on a storage-touching endpoint, and fail on a 5xx (the existing log-grep then surfaces the server-side 500). Because startup (~10 min) finishes well before pytest (~21 min) gates the merge, this added request-level coverage is effectively free on wall-clock — it fills the ~11 min of headroom rather than extending the critical path.
Filed via Claude Code on Evan's behalf.
Problem
The
startupCI stage (test_startup.sh) only asserts that the server boots — it greps the startup output forNiceGUI ready to goand the absence ofTraceback|Error, but it never issues an HTTP request. So any regression that is latent until a request slips straight through.#6061 is the concrete case: #5960 set
Storage.path = Noneat import time (clobbered transitively via the docs'from nicegui.testing import ...). The server boots fine; the crash —TypeError: unsupported operand type(s) for /: 'NoneType' and 'str'in_create_user_storage→Storage.path / f'storage-{id}.json'— only fires on the first storage-touching request. With no client connecting during the startup job's window, that code path is never exercised, so the job stays green.Evidence
All
full-test / {3.10–3.14} / startupjobs passed on the #5960 merge commit5328b594; the regression was reported by a user (#6061), not caught by CI.Empirical repro + CI timings
main.pyon0a1e6597(reapplied Randomize test ports/dirs for parallel pytest sessions #5960, pre-fix) and issue one request to any page that usesapp.storage.user→ 500 with theNoneType / strtraceback. The traceback travels the HTTP request path (uvicorn → _create_user_storage), so a single request during the startup window would have tripped the existinggrep -qE "Traceback|Error"intest_startup.sh. CI simply never sends one.startup≈ 10 min,pytest≈ 21 min (per Python version, n=5). The merge gate is bound by the ~21 minpytestjob, and thestartupjob finishes ~11 min earlier.Proposed fix
After
NiceGUI ready to go, havetest_startup.shhit the running server with at least one real request — the main website and each example — on a storage-touching endpoint, and fail on a 5xx (the existing log-grep then surfaces the server-side 500). Becausestartup(~10 min) finishes well beforepytest(~21 min) gates the merge, this added request-level coverage is effectively free on wall-clock — it fills the ~11 min of headroom rather than extending the critical path.