JSON.parse Silently Corrupts Large Integers—and the Reviver Can't Save You
A single silently-corrupted ID can route users to wrong records, break audit trails, or cause data writes against the wrong entity—all without a stack trace. Most teams won't catch this in development because small test IDs parse fine; the bug only surfaces in production with real large identifiers.
A production bug where user detail pages kept loading the wrong person traced back to a 19-digit user ID. The backend stored and transmitted the correct number, but JSON.parse silently rounded the last digits, producing a different ID. No error was thrown, no warning logged—just silently corrupted data.
The root cause is JavaScript's IEEE 754 double-precision limit: integers larger than 9,007,199,254,740,991 lose precision. A common frontend fix using the reviver parameter fails because the number is already truncated before the reviver runs. The only reliable client-side path is a library like json-bigint that converts large numbers to BigInt during parsing.
The simplest fix is on the backend: serialize any integer over 16 digits as a string. For teams on gRPC or protobuf, proto3's int64 already defaults to string in JavaScript, sidestepping the issue entirely.
The reviver-based fix is widely shared online as a solution but is fundamentally broken—it operates on already-corrupted data. This makes it a dangerous piece of cargo-cult advice.
The bug's non-deterministic nature (only large IDs trigger it) means it survives QA and staging, making it a classic 'works on my machine' production time bomb.
The JSON spec itself has no integer size limit, but JavaScript's number type does—this is a language-level impedance mismatch, not a bug in either system, which is why blame ping-pongs between frontend and backend teams.