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

  1. Append n to make it a BigInt literal when exact integer arithmetic is needed: 9007199254740993n
  2. Otherwise choose the nearest representable value explicitly (9007199254740992) so source and runtime agree
  3. 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

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


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/0fbd3667892fbfd1. Report an issue: GitHub.