Repository navigation
Codegen regression: every /api/* request crashes the process with 'TypeError: value is not a function at <anonymous>' (fresh compiles after May 10–15) #922
Description
Symptom
A binary that compiles cleanly with the current Perry (32352733) crashes the process on every Fastify route hit that isn't /health, with this loop in stderr:
[WARN_NULL_PTR] js_object_set_field: null POINTER_TAG at obj=0x200002114a0 field_index=0 class_id=0 — replacing with undefined
TypeError: value is not a function
at <anonymous>
[WARN_NULL_PTR] js_object_set_field: null POINTER_TAG at obj=0x200002114a0 field_index=0 class_id=0 — replacing with undefined
TypeError: value is not a function
at <anonymous>
...
The same at <anonymous> repeats indefinitely (no symbolized frame) until PM2 marks the process as errored.
Repro
gscmaster-api, ~5k lines of TS, Fastify shim + mysql2 + fetch. The exact same source compiled by a Perry from before ~May 10 produces a binary that handles /api/* fine (returns 401 for unauth /api/sites, etc.). A fresh compile today produces a binary where:
| endpoint | result |
|---|---|
GET /health |
200 ✓ |
GET /api/sites (no Authorization header) |
tight loop of `TypeError: value is not a function` → process exits → PM2 restart |
any other /api/* |
same |
Notably, /health works — so module init, fastify setup, route registration, and the request loop are all functional. It's the dispatch to a registered handler that explodes.
For /api/sites, the handler body starts with await authMiddleware(request, reply);. With no auth header, that should reply.status(401).send({error:"Unauthorized"}) and return. Even calling it directly without ever entering the handler body would be enough to trigger the crash.
Bisect window
- Works: binary compiled May 10 (Perry HEAD then; current
/opt/perryshows last build May 15 18:08, several commits ahead). Binary still runs fine — request loop OK, only the bg-refresh cron crashes (filed separately). - Broken: any fresh compile from Perry at
32352733(the May 15+ rebuild), even of the byte-identical source the May 10 binary came from, with only the minimum changes the new compiler now requires:crypto.hmacSha256(data, key)→crypto.createHmac(\"sha256\", key).update(data).digest(\"hex\")(new compiler errors out: `'crypto.hmacSha256' is not implemented in Perry — see 'perry --print-api-manifest'`)require(\"crypto\")andrequire(\"jose\")removed (new compiler errors: `CommonJS `require("jose")` is not supported under `perry compile` — use a static `import` instead. Closes AOT:require('./mod')from inside a class method returns a non-callable value #668.`)const pool = ...; export { pool };→export const pool = ...(new compiler linker error: `undefined reference to `__perry_wrap_perry_fn_db_ts__pool'`)
After those three mechanical changes (no behavior change), compile succeeds, link succeeds — but the resulting binary crashes every /api/* hit. The May 10 binary (with the older patterns the compiler now rejects) is the only build of this code that handles requests.
Diagnostic dead ends
- The errors print without a symbol —
at <anonymous>only. Addingconsole.logat the top ofauthMiddlewaredoesn't show — the crash is before the handler body runs. /healthregistered the same way works, so route-handler dispatch broadly works.- The error message
value is not a functionsuggests a missing/undefined symbol being invoked — possibly an internal handler-binding object whose method slot is null.
Asks
- Bisect the Perry tree between May 10 (last known-good build) and
32352733to find the regressing commit. Likely candidates judging by titles: any change to fastify route dispatch, closure binding, or the request-handler ABI. - If a quick fix isn't possible, a way to dump the offending callsite (which symbol resolved to undefined?) — currently the user has no path forward from `at `.
Environment
- Perry HEAD:
32352733(the May 15+ rebuild) - Last known-good Perry: pre-May 10 (whatever produced
/opt/gscmaster-api/gscmaster-api.bak, 34MB binary, May 17 16:59 mtime) - Target: x86_64 Ubuntu 22.04
- Project: gscmaster-api (Fastify + mysql2 + fetch, ~5k LoC TS)
Happy to provide the full source + the broken/working binaries to whoever takes this. Production has been running on the known-good binary for 7 days; the only thing blocking deployment of new features is this regression.
Activity
fix(runtime): #922 — circuit breaker for runaway `value is not a func…
fix(runtime): #922 — circuit breaker for runaway `value is not a func…
fix(ci): add http.METHODS/STATUS_CODES to manifest + 4 known_failures…
fix(runtime): align Invalid Date ISO parity (#938)
test(parity): re-validate known_failures skip-list against v0.5.1026 (#…
fix(runtime): don't count caught throws toward the throw circuit-brea…
fix(gc): give the six unpruned rekeyed tables a death story (#8190-#8195
fix(gc): give the six unpruned rekeyed tables a death story (#8190-#8195
fix(gc): refuse a forwarding walk out of, or into, a non-object, and …