Skip to content

Native shop-admin signup SIGBUS in toUser → dtRequiredToIso (downstream of @perryts/mysql MyDateTime.toDate corruption) #859

@proggeramlug

Description

@proggeramlug

Symptom

Native-compiled skelpo-shop-admin (./build/server) at perry 0.5.914 crashes with SIGBUS / exit 138 during POST /v1/auth/signup. The first INSERT INTO users commits (visible in MySQL), then the process dies — curl gets Empty reply from server and the connection drops. tsx server/main.ts against the same source + same DB returns the correct JSON / HTTP 201.

This is the v0.5.914 surfacing of what at v0.5.912 was a silent body-0/HTTP 200 — same site, harder failure now that the Invalid-Date sentinel is in.

Pinned crash site (checkpoint-instrumented trace)

Instrumented server/persistence/users.ts::createUser/getUserById/toUser:

U1 INSERT                      ← createUser INSERT runs
U2 done, pre getUserById       ← INSERT resolved, row visible
G1 pre queryOne                ← getUserById entered
G2 queryOne obj                ← SELECT returned the row
T0 enter   (toUser entered)
T1 id=019e2fac-...             ← bufToId(r.id) works
T2 emailVerified=null          ← dtToIso(null) works
T3 totp=null                    ← dtToIso(null) works
                                ← SIGBUS. No T4.

Next statement is dtRequiredToIso(r.createdAt), which calls r.createdAt.toDate().getTime() on the MyDateTime object the @perryts/mysql driver decoded. That .toDate() call is where the process dies.

Root cause

The proximate trigger is #788 — closure-captured numeric params read as 0 inside object-literal : Date method (filed separately). MyDateTime.toDate() is exactly that shape, so for every decoded DATETIME the captured y/mo/d/... read as 0 inside the method and new Date(Date.UTC(0, ...)) produces a year-0 Date (-62155492224598 ms). When that value flows into dtRequiredToIso → d.toISOString() and the resulting string into perry's JSON / fastify reply path, something in the formatting / serialization chain assumes a finite, plausible timestamp and segfaults.

In a standalone repro of just the MyDateTime.toDate().toISOString() shape (no Fastify, no mysql connection — see #788) the same code returns a garbage 0000-05-15T17:29:36.598Z string without crashing. The shop-admin path additionally goes through fastify's JSON reply, the post-#748 wait_for_promise condvar path, and likely the @perryts/mysql worker-thread → main-thread Date hand-off. One of those layers can't survive a year-0 / Invalid Date and faults.

Repro

Local: clean checkout of skelpo-shop-admin, cargo build --release of perry at HEAD (e18cdb07 / v0.5.914), then:

mysql -uroot -e "DROP DATABASE IF EXISTS shopadmin; CREATE DATABASE shopadmin"
KEK_BASE64=... JWT_SIGNING_KEY_PEM=... DB_DSN='mysql://root:@127.0.0.1:3306/shopadmin' \
  BIND_ADDR='127.0.0.1:18080' ./build/server &
curl -X POST http://127.0.0.1:18080/v1/auth/signup \
     -H 'content-type: application/json' \
     -d '{"email":"x@y.com","password":"correct-horse-battery-staple","accountName":"X"}'
# → curl: (52) Empty reply from server; server process exits 138.

tsx server/main.ts against the same DB+env returns the correct {accessToken, refreshToken, expiresAt, user, account} payload with HTTP 201 and all five tables populated.

Tracking history

This is the same end-user failure that drove #665 and #748:

Suggested fix scope

  1. Fix AsyncLocalStorage: real async-context tracking across await / microtasks / timers #788 (the captures) — that should be enough for the user's signup to work end-to-end. The corrupt-Date path stops producing year-0 values and toISOString returns the real timestamp.
  2. Independently, find the downstream layer that segfaults on a year-0/Invalid Date and harden it — same value at the same call site shouldn't take down the process. (My standalone repro of the same shape returns a garbage string without crashing, so the segfault is specific to one of: fastify reply path, @perryts/mysql worker→main thread Date crossing, or wait_for_promise resuming with a Date argument it doesn't expect.)

Perry version at repro: 0.5.914.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions