Skip to content

fix: prevent IEEE 754 precision loss in OTLP nanosecond timestamps#3378

Closed
aayushbaluni wants to merge 1 commit intotriggerdotdev:mainfrom
aayushbaluni:fix/3292-nanosecond-bigint-overflow
Closed

fix: prevent IEEE 754 precision loss in OTLP nanosecond timestamps#3378
aayushbaluni wants to merge 1 commit intotriggerdotdev:mainfrom
aayushbaluni:fix/3292-nanosecond-bigint-overflow

Conversation

@aayushbaluni
Copy link
Copy Markdown

Summary

Several places in the webapp multiply epoch milliseconds by 1,000,000 before converting to BigInt, which causes IEEE 754 precision loss (~256ns errors in ~0.2% of cases). The result exceeds Number.MAX_SAFE_INTEGER (~9e15) since epoch-ms × 1e6 is ~1.7e18.

Root Cause

// Bug: multiplication in float-land before BigInt conversion
BigInt(new Date().getTime() * 1_000_000);

// Fix: multiply after BigInt conversion
BigInt(new Date().getTime()) * BigInt(1_000_000);

The correct pattern already existed in convertDateToNanoseconds() in the same file — the other functions just didn't use it.

Changes

  • common.server.ts: Fix getNowInNanoseconds(), calculateDurationFromStart(), and calculateDurationFromStartJsDate()
  • index.server.ts: Fix recordRunDebugLog() startTime calculation

All four locations now convert to BigInt before multiplication, consistent with the existing convertDateToNanoseconds() implementation.

Fixes #3292

Made with Cursor

Multiplying epoch milliseconds by 1,000,000 before BigInt conversion
produces values exceeding Number.MAX_SAFE_INTEGER (~9e15), causing
~256ns precision errors in ~0.2% of timestamps.

Convert to BigInt first, then multiply:
- getNowInNanoseconds(): BigInt(ms) * BigInt(1_000_000)
- calculateDurationFromStart(): same pattern
- calculateDurationFromStartJsDate(): same pattern
- recordRunDebugLog(): same pattern

The correct pattern already existed in convertDateToNanoseconds() in
the same file.

Fixes triggerdotdev#3292

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 427a3232-5da1-412e-8930-eab0563819be

📥 Commits

Reviewing files that changed from the base of the PR and between 73ea586 and 170c1f3.

📒 Files selected for processing (2)
  • apps/webapp/app/v3/eventRepository/common.server.ts
  • apps/webapp/app/v3/eventRepository/index.server.ts

Walkthrough

The changes refactor nanosecond conversion logic in two event repository files to perform BigInt arithmetic before multiplication rather than after. Functions getNowInNanoseconds(), calculateDurationFromStart(), calculateDurationFromStartJsDate() in common.server.ts, and recordRunEvent() in index.server.ts are updated to convert JavaScript numbers to BigInt first, then multiply by 1,000,000 using BigInt operands. No exported function signatures were altered. The total changes span two files with minimal line modifications.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

Hi @aayushbaluni, thanks for your interest in contributing!

This project requires that pull request authors are vouched, and you are not in the list of vouched users.

This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details.

@github-actions github-actions bot closed this Apr 15, 2026
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

⚠️ 1 issue in files not directly in the diff

⚠️ Missed instance of the same BigInt overflow pattern at runEngineHandlers.server.ts:432 (apps/webapp/app/v3/runEngineHandlers.server.ts:432)

This PR fixes the BigInt(timestamp * 1_000_000) overflow pattern in 4 locations, but missed the same bug at apps/webapp/app/v3/runEngineHandlers.server.ts:432. The expression BigInt(time.getTime() * 1000000) suffers from the same Number.MAX_SAFE_INTEGER overflow: Date.getTime() returns ~1.78e12 and multiplying by 1,000,000 gives ~1.78e18 which exceeds Number.MAX_SAFE_INTEGER (9.007e15), causing precision loss before the BigInt conversion. At the current date, this causes a ~64-nanosecond error in the recorded startTime of retry-scheduled events.

View 3 additional findings in Devin Review.

Open in Devin Review

aayushbaluni added a commit to aayushbaluni/trigger.dev that referenced this pull request Apr 15, 2026
Fixes triggerdotdev#3292

Multiple functions compute nanosecond timestamps as
BigInt(milliseconds * 1_000_000). When milliseconds exceed
Number.MAX_SAFE_INTEGER / 1_000_000 (≈ 9.007e9, i.e. any date
after ~1970-04-15), the multiplication overflows IEEE 754 precision
before the BigInt conversion captures it.

Fix all instances (including runEngineHandlers.server.ts:432 which
was missed in the previous PR triggerdotdev#3378) by converting to BigInt first:
BigInt(milliseconds) * BigInt(1_000_000)

Made-with: Cursor
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.

OTLP nanosecond timestamp overflow in webapp event repository

1 participant