oxc-project/oxc · error · OxcDiagnostic
This number literal will lose precision at runtime.
Error message
This number literal will lose precision at runtime.
What it means
Diagnostic from oxlint's eslint/no-loss-of-precision rule (crates/oxc_linter/src/rules/eslint/no_loss_of_precision.rs:12). It reports a numeric literal whose value cannot be represented exactly as an IEEE-754 double: Number only represents integers exactly up to 9007199254740991 (2**53 - 1), and most decimal fractions are inexact. The literal silently becomes a different number at runtime, so the source code lies about the value (e.g. 9007199254740993 evaluates to 9007199254740992).
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_loss_of_precision.rs:12
use std::borrow::Cow;
use cow_utils::CowUtils;
use oxc_ast::{AstKind, ast::NumericLiteral};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{AstNode, context::LintContext, rule::Rule};
fn no_loss_of_precision_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("This number literal will lose precision at runtime.")
.with_help(
"Use a number literal representable by a 64-bit floating-point number, or use a `BigInt` literal (for example, `9007199254740993n`) for exact large integers.",
)
.with_note(
"In JavaScript, `Number` values exactly represent integers only in the range -9007199254740991 to 9007199254740991 (`Number.MIN_SAFE_INTEGER` to `Number.MAX_SAFE_INTEGER`). `BigInt` supports arbitrarily large integers.",
)
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoLossOfPrecision;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow precision loss in numeric literals.
///
/// ### Why is this bad?View on GitHub (pinned to e1e7af627c)
Solutions
- Append n to make it a BigInt literal when exact integer arithmetic is needed: 9007199254740993n
- Otherwise choose the nearest representable value explicitly (9007199254740992) so source and runtime agree
- For IDs from external systems, keep them as strings end-to-end instead of numeric literals
Example fix
// before const tweetId = 9007199254740993; // evaluates to 9007199254740992 // after const tweetId = 9007199254740993n; // BigInt, exact // or, if it must be a Number: const tweetId = '9007199254740993'; // string ID
Defensive patterns
Strategy: validation
Validate before calling
// Guard for hardcoded numeric IDs/constants in codegen or templates
function assertExactAsNumber(literal) {
const n = Number(literal);
if (Number.isInteger(n) && !Number.isSafeInteger(n)) {
throw new RangeError(`${literal} loses precision as Number; use BigInt or string`);
}
}
assertExactAsNumber(9007199254740993); Type guard
function isExactlyRepresentable(literal) {
const n = Number(literal);
return Number.isInteger(n) ? Number.isSafeInteger(n) : String(n).length >= String(literal).replace(/^0+|0+$/g, '').length - 1;
} Prevention
- Treat external IDs as strings from the API boundary inward
- Use BigInt (n suffix) for values beyond 2**53 - 1
- Enable no-loss-of-precision in CI so silent rounding cannot land
When it happens
Trigger: Integer literals beyond Number.MAX_SAFE_INTEGER (const id = 9007199254740993;); literals with more decimal digits than a double can hold (const x = 0.10000000000000000001; evaluates to 0.1); very long literals copied from databases, snowflake IDs, or documentation.
Common situations: Hard-coding Twitter/X snowflake IDs, big user IDs, or blockchain amounts as Number literals; porting constants from Python/Java (arbitrary/big integers) to JS; test fixtures copy-pasted with full-precision expected values.
Related errors
- Function declared in a loop contains unsafe references to va
- Empty array binding pattern
- Empty object binding pattern
- React Hook {hook_name:?} cannot be called inside a callback.
- `debugger` statement is not allowed
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/0fbd3667892fbfd1.
Report an issue: GitHub.