Relationships
#1899 swamp serve panics on successful OAuth device-flow completion (Deno HTTP invariant)
Opened by sntxrr · 8/28/2026· Shipped 9/1/2026
Summary
Completing an OAuth device-flow login against swamp serve reliably panics the
process. The panic is a Rust-level abort inside Deno's HTTP layer, so there is
no JS stack and no graceful shutdown — the whole server dies.
Reproduced 2 out of 2 attempts, minutes apart, on the same build.
Environment
- swamp
20260828.202201.0-sha.2a5bcb89 swamp serve --auth-mode oauth --oauth-provider https://<INTERNAL_HOST> --dashboard --host 0.0.0.0- Login initiated from the
--dashboardweb UI (device flow), approved in the upstream IdP - Self-hosted authorization server (an OIDC shim in front of Authentik)
- Running in Docker;
restart: unless-stoppedis what brings it back
What happens
The device flow succeeds server-side, and then the process aborts:
system │ Device grant started for provider "https://<INTERNAL_HOST>"
system │ Minted OAuth server token "oauth-<REDACTED>" for "user:<USERNAME>"
system │ Stored OAuth access token for "oauth-<REDACTED>"
system │ OAuth device flow completed for "user:<USERNAME>"
thread 'main' (1) panicked at ext/http/service.rs:794:5:
HTTP state error: Expected to be last strong reference
note: run with `RUST_BACKTRACE=1` environment variable to display a backtraceThe token is minted and stored, but the response never reaches the browser — the process is gone before it is delivered. The container's restart count incremented on both occasions.
Reproduction
- Run
swamp serve --auth-mode oauth --oauth-provider <non-swamp-club server> --dashboard - Open
/dashboardand click the login button - Approve the device code at the IdP
- Serve panics within a few seconds of approval
Impact
- OAuth login via the dashboard cannot complete. Succeeding is what kills it, so there is no way through by retrying.
- Because it is a process-level abort, everything else the instance owns goes with it. On this deployment that includes the scheduler, so every cron trigger is interrupted and re-registered on restart (~40 s outage per login attempt).
- The client sees no error at all — see the companion report on the dashboard's device-poll error handling, which renders every failure as an indefinite "Waiting for you to approve...".
Notes toward a cause
Offered as observation, not diagnosis — the panic is in Deno, not swamp:
src/serve/device_auth_handler.tsbuilds an ordinaryjsonResponse(200, ...)and returns it; nothing in the handler itself looks unusual.packages/dashboard/src/views/Login.tsx:164pollsPOST /auth/device/tokenon a baresetIntervalwith noAbortControllerand no in-flight guard. A poll that is still open when the next one fires — likely around the slow upstream token exchange — leaves overlapping requests on the same connection.Expected to be last strong referenceis consistent with a request's HTTP state being dropped while another reference is still live.- Worth checking whether the CLI path (
swamp auth server-login), which polls differently, is affected too. Not tested here.
Suggested mitigations
Independent of the underlying Deno issue, either of these would reduce blast radius:
- Guard the poll client-side: skip a tick while a request is in flight, and abort the previous request before issuing a new one.
- Catch the panic boundary so a single request cannot take down a server that may also be running scheduled workflows.
Shipped
Click a lifecycle step above to view its details.