Skip to content

util.inspect incorrectly formats negative fractional numbers with numericSeparator: true #59376

Description

@thoukydides

Version

v24.5.0 (also reproduced on v20.19.2)

Platform

Linux nexus 6.14.0-27-generic #27~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 17:38:49 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

util

What steps will reproduce the bug?

import { inspect } from 'util';

const values = [0.1234, -0.12, -0.123, -0.1234, -1.234];
const text = inspect(values, { numericSeparator: true });
console.log(text);

How often does it reproduce? Is there a required condition?

Always reproducible for negative numbers strictly between -1 and 0, when numericSeparator: true is specified.

What is the expected behavior? Why is that the expected behavior?

The output should be syntactically valid JavaScript numeric literals representing the original values, with numeric separators inserted in accordance with the numericSeparator option. For the sample above, the expected output is::

[ 0.123_4, -0.12, -0.123, -0.123_4, -1.234 ]

What do you see instead?

The actual output of the sample script is:

[ 0.123_4, 0..12, 0..12_3, 0..12_34, -1.234 ]

The three incorrect values:

  • Are missing their leading minus sign
  • Contain a spurious double decimal point (0..)
  • Place the numeric separator incorrectly

Additional information

No response

Activity

  1. thoukydides commented on Aug 6, 2025

    @thoukydides
    Author

    I believe the bug is caused by the following formatNumber code in lib/internal/util/inspect.js:

      const integer = MathTrunc(number);
      const string = String(integer);
      ...
      return fn(`${
        addNumericSeparator(string)
      }.${
        addNumericSeparatorEnd(
          StringPrototypeSlice(String(number), string.length + 1),
        )
      }`, 'number');
    }

    For values where -1 < number < 0, this results in:

    • integer === -0 (correct)
    • string === '0' (loses the leading minus sign due to coercion)
    • addNumericSeparator(string) omits the minus sign from the formatted number
    • StringPrototypeSlice(String(number), string.length + 1) incorrectly retains the original decimal point, resulting in a duplicated dot (..) in the output

    One potential fix would be to use logic similar to the non-numericSeparator case earlier in the function:

      const string = ObjectIs(number, -0) ? '-0' : String(integer);

    However, a cleaner and more robust approach might be to either:

    • Remove the sign before applying numeric separators, and prepend the minus sign to the final output if number < 0 || ObjectIs(number, -0); or
    • Perform the string conversion once, then locate the decimal point (if any) and split the string appropriately for formatting.
  2. added
    confirmed-bugIssues and PRs for confirmed bugs.
    utilIssues and PRs related to the built-in util module.
    on Aug 6, 2025
  3. Han5991 commented on Aug 6, 2025

    @Han5991
    Contributor

    I'll give it a try?

  4. BridgeAR commented on Aug 6, 2025

    @BridgeAR
    Member

    I would either go with the quick fix suggested here or by performing the string conversion once.

    @Han5991 go ahead. If you open a PR, please reference this issue with Closes #59376.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.utilIssues and PRs related to the built-in util module.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions