Skip to content

fix(thrift): serialize bigint I64 fields as hex to avoid node-int64 corruption (MESSAGE_NOT_FOUND)#194

Merged
EdamAme-x merged 1 commit into
mainfrom
fix/thrift-i64-bigint-serialization
Jun 18, 2026
Merged

fix(thrift): serialize bigint I64 fields as hex to avoid node-int64 corruption (MESSAGE_NOT_FOUND)#194
EdamAme-x merged 1 commit into
mainfrom
fix/thrift-i64-bigint-serialization

Conversation

@EdamAme-x

Copy link
Copy Markdown
Member

Summary

Fixes #193.

bigint I64 fields (e.g. a message ID passed to talk.react()) were serialized incorrectly by the Thrift writer. The value was handed to the node-int64 constructor as a decimal string via val.toString(), but node-int64 interprets a bare string argument as hex. A message ID like 618946633287860670n was therefore truncated to a completely different value on the wire, and the LINE server rejected it with MESSAGE_NOT_FOUND / NO_MESSAGE.

Fix

packages/linejs/base/thrift/readwrite/write.ts

-output.writeI64(new Int64(val.toString()));
+output.writeI64(
+	new Int64("0x" + BigInt.asUintN(64, val).toString(16).padStart(16, "0")),
+);

This builds a 0x-prefixed, zero-padded 16-char hex string, which node-int64 parses correctly. Using BigInt.asUintN(64, val) (rather than the plain "0x" + val.toString(16) from the issue) additionally keeps negative I64 values correct by emitting their full two's-complement bytes instead of zero-extending the low 32 bits.

value before (decimal→hex misparse) after
618946633287860670n 8946633287860670 0896f0af040c01be
-5n fffffffffffffffb

Tests

Adds packages/linejs/base/thrift/readwrite/write.test.ts:

  • round-trips the issue's exact > Number.MAX_SAFE_INTEGER message ID through writeThrift/readThrift (binary + compact protocols),
  • pins the exact 64-bit big-endian wire octets,
  • covers negative (two's-complement) and small bigint values.
deno test -A packages/linejs/base/thrift/readwrite/write.test.ts   # 4 passed
deno publish --dry-run   # linejs + types: Success

Co-authored-by: [As]ReMix remixasoom@gmail.com

…orruption

The Thrift writer passed bigint I64 values to the node-int64 constructor as a
decimal string (`val.toString()`). node-int64 interprets a bare string as hex,
so a message ID like 618946633287860670n was silently truncated to a different
value on the wire, causing the LINE server to return MESSAGE_NOT_FOUND /
NO_MESSAGE (e.g. talk.react()).

Encode the value as a `0x`-prefixed, zero-padded 16-char hex string built from
`BigInt.asUintN(64, val)`. This preserves full 64-bit precision for positive
values and correctly emits two's-complement bytes for negative I64 values.

Adds round-trip and exact-wire-octet regression tests for the Thrift writer.

Fixes #193

Co-authored-by: [As]ReMix <remixasoom@gmail.com>
@EdamAme-x EdamAme-x merged commit 5e9491b into main Jun 18, 2026
4 checks passed
@EdamAme-x EdamAme-x deleted the fix/thrift-i64-bigint-serialization branch June 18, 2026 13:26
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.

Bug: bigint (I64) fields serialized incorrectly in Thrift writer due to node-int64 string parsing behavior (causes MESSAGE_NOT_FOUND on reactions)

1 participant