Skip to content

Codegen regression: every /api/* request crashes the process with 'TypeError: value is not a function at <anonymous>' (fresh compiles after May 10–15) #922

Closed

Description

@proggeramlug

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/perry shows 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\") and require(\"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. Adding console.log at the top of authMiddleware doesn't show — the crash is before the handler body runs.
  • /health registered the same way works, so route-handler dispatch broadly works.
  • The error message value is not a function suggests a missing/undefined symbol being invoked — possibly an internal handler-binding object whose method slot is null.

Asks

  1. Bisect the Perry tree between May 10 (last known-good build) and 32352733 to find the regressing commit. Likely candidates judging by titles: any change to fastify route dispatch, closure binding, or the request-handler ABI.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions