Skip to content

fix(api): safe BigInt parse — 400 on bad cursor instead of 500 crash#12

Merged
satyakwok merged 1 commit into
mainfrom
fix/api-safe-bigint-parse
May 7, 2026
Merged

fix(api): safe BigInt parse — 400 on bad cursor instead of 500 crash#12
satyakwok merged 1 commit into
mainfrom
fix/api-safe-bigint-parse

Conversation

@satyakwok
Copy link
Copy Markdown
Member

Bug

Five endpoints did raw BigInt(req.query.*) / BigInt(req.params.*):

  • /blocks?before=...
  • /blocks/:height
  • /coinblast/tokens?before=...
  • /coinblast/trades?before=...
  • /coinblast/trades/by-curve/:curve?after=...

When user passes non-numeric input (?before=abc), BigInt() throws SyntaxError. Fastify returns 500 with no actionable message + alerter noise.

Fix

parseBigIntOrThrow helper wraps BigInt() in try/catch + throws InvalidQueryError. Each route catches + returns 400 with field-named message. Defined in both route files (small enough to inline).

Verified

tsc --noEmit clean.

Five endpoints did raw BigInt(req.query.*) / BigInt(req.params.*):
  native.ts:    /blocks?before=...      /blocks/:height
  coinblast.ts: /coinblast/tokens?before=...
                /coinblast/trades?before=...
                /coinblast/trades/by-curve/:curve?after=...

When user passes non-numeric input (e.g. ?before=abc), BigInt() throws
SyntaxError. Fastify catches and returns 500 internal server error with
no actionable message. Should be 400 bad request.

Fix: parseBigIntOrThrow helper wraps BigInt() in try/catch + throws an
InvalidQueryError class. Each route catches the error and returns
400 with field-named message. Internal 500s drop, user gets
actionable error, alerter stays quiet.

Per-route handler signature changes: routes that previously didn't
accept reply now do (added 'reply' param to enable code(400) calls).

tsc --noEmit clean across both files.
@satyakwok satyakwok merged commit 6fbb1e1 into main May 7, 2026
@satyakwok satyakwok deleted the fix/api-safe-bigint-parse branch May 7, 2026 11:12
satyakwok added a commit that referenced this pull request May 7, 2026
Same class as #12 — ${threshold}::numeric in the underlying SQL was
dropping bad input straight to Postgres. 'abc' returned a 22P02 500
('invalid input syntax for type numeric') instead of a clean 400.
Drizzle's sql`` parameterizes so this isn't an injection path
(verified — semicolons go through as parameter values, no DROP),
just a leak of internal Postgres error codes + alerter noise.

Reuse parseBigIntOrThrow — wei thresholds are integers anyway, no
decimal needed. Bad threshold now returns 400 with a clear message.

Co-authored-by: satyakwok <satyakwok@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant