nodejs / nodejs/node

`util.inspect()` ignores `breakLength: Infinity` when `depth: Infinity` is also set in some cases

Abierto
#60,475 4 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

confirmed-bug util
Lenguaje dominante
JavaScript
Estrellas
122k
Forks
37.3k
Merge medio
4 d 2 h
PR fusionados (30 d)
283

Descripción

Version

v25.1.0

Platform
- Windows: Microsoft Windows NT 10.0.26200.0 x64
- macOS: Darwin MacBook-Pro.local 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:51 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T8112 arm64
- Linux: Linux myhost 6.8.0-45-generic #45-Ubuntu SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
Subsystem

util

What steps will reproduce the bug?

When util.inspect() is called with both breakLength: Infinity and depth: Infinity, the output unexpectedly contains line breaks in Node.js v25.x.

In contrast:

  • Using only breakLength: Infinity (with default depth) works correctly and produces a single-line output.
  • The issue appears only when depth is explicitly set to Infinity.

This behavior did not occur in Node.js v24.x, so it appears to be a regression.

A minimal reproducible example is provided below.

$ nvm use 24
Now using node v24.11.0 (npm v11.6.1)
$ node
Welcome to Node.js v24.11.0.
Type ".help" for more information.
> const util = require("node:util")
undefined
> util.inspect(util, { breakLength: Infinity })
"{ _errnoException: [Function: _errnoException], _exceptionWithHostPort: [Function: _exceptionWithHostPort], _extend: [Function: deprecated], callbackify: [Function: callbackify], debug: [Function: debuglog], debuglog: [Function: debuglog], deprecate: [Function: deprecate], format: [Function: format], styleText: [Function: styleText], formatWithOptions: [Function: formatWithOptions], getCallSites: [Function: getCallSites], getSystemErrorMap: [Function: getSystemErrorMap], getSystemErrorName: [Function: getSystemErrorName], getSystemErrorMessage: [Function: getSystemErrorMessage], inherits: [Function: inherits], inspect: [Function: inspect] { custom: Symbol(nodejs.util.inspect.custom), colors: [Object: null prototype] { reset: [Array], bold: [Array], dim: [Array], italic: [Array], underline: [Array], blink: [Array], inverse: [Array], hidden: [Array], strikethrough: [Array], doubleunderline: [Array], black: [Array], red: [Array], green: [Array], yellow: [Array], blue: [Array], magenta: [Array], cyan: [Array], white: [Array], bgBlack: [Array], bgRed: [Array], bgGreen: [Array], bgYellow: [Array], bgBlue: [Array], bgMagenta: [Array], bgCyan: [Array], bgWhite: [Array], framed: [Array], overlined: [Array], gray: [Array], redBright: [Array], greenBright: [Array], yellowBright: [Array], blueBright: [Array], magentaBright: [Array], cyanBright: [Array], whiteBright: [Array], bgGray: [Array], bgRedBright: [Array], bgGreenBright: [Array], bgYellowBright: [Array], bgBlueBright: [Array], bgMagentaBright: [Array], bgCyanBright: [Array], bgWhiteBright: [Array] }, styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: 'red', module: 'underline' }, replDefaults: [Getter/Setter] }, isArray: [Function: deprecated], isDeepStrictEqual: [Function: isDeepStrictEqual], promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) }, stripVTControlCharacters: [Function: stripVTControlCharacters], toUSVString: [Function: toUSVString], transferableAbortSignal: [Getter], transferableAbortController: [Getter], aborted: [Getter], types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] }, parseEnv: [Function: parseEnv], parseArgs: [Function: parseArgs], TextDecoder: [class TextDecoder], TextEncoder: [class TextEncoder], MIMEType: [class MIMEType], MIMEParams: [class MIMEParams], diff: [Function: diff], setTraceSigInt: [Function: setTraceSigInt] }"
> util.inspect(util, { breakLength: Infinity, depth: Infinity })
"{ _errnoException: [Function: _errnoException], _exceptionWithHostPort: [Function: _exceptionWithHostPort], _extend: [Function: deprecated], callbackify: [Function: callbackify], debug: [Function: debuglog], debuglog: [Function: debuglog], deprecate: [Function: deprecate], format: [Function: format], styleText: [Function: styleText], formatWithOptions: [Function: formatWithOptions], getCallSites: [Function: getCallSites], getSystemErrorMap: [Function: getSystemErrorMap], getSystemErrorName: [Function: getSystemErrorName], getSystemErrorMessage: [Function: getSystemErrorMessage], inherits: [Function: inherits], inspect: [Function: inspect] { custom: Symbol(nodejs.util.inspect.custom), colors: [Object: null prototype] { reset: [ 0, 0 ], bold: [ 1, 22 ], dim: [ 2, 22 ], italic: [ 3, 23 ], underline: [ 4, 24 ], blink: [ 5, 25 ], inverse: [ 7, 27 ], hidden: [ 8, 28 ], strikethrough: [ 9, 29 ], doubleunderline: [ 21, 24 ], black: [ 30, 39 ], red: [ 31, 39 ], green: [ 32, 39 ], yellow: [ 33, 39 ], blue: [ 34, 39 ], magenta: [ 35, 39 ], cyan: [ 36, 39 ], white: [ 37, 39 ], bgBlack: [ 40, 49 ], bgRed: [ 41, 49 ], bgGreen: [ 42, 49 ], bgYellow: [ 43, 49 ], bgBlue: [ 44, 49 ], bgMagenta: [ 45, 49 ], bgCyan: [ 46, 49 ], bgWhite: [ 47, 49 ], framed: [ 51, 54 ], overlined: [ 53, 55 ], gray: [ 90, 39 ], redBright: [ 91, 39 ], greenBright: [ 92, 39 ], yellowBright: [ 93, 39 ], blueBright: [ 94, 39 ], magentaBright: [ 95, 39 ], cyanBright: [ 96, 39 ], whiteBright: [ 97, 39 ], bgGray: [ 100, 49 ], bgRedBright: [ 101, 49 ], bgGreenBright: [ 102, 49 ], bgYellowBright: [ 103, 49 ], bgBlueBright: [ 104, 49 ], bgMagentaBright: [ 105, 49 ], bgCyanBright: [ 106, 49 ], bgWhiteBright: [ 107, 49 ] }, styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: 'red', module: 'underline' }, replDefaults: [Getter/Setter] }, isArray: [Function: deprecated], isDeepStrictEqual: [Function: isDeepStrictEqual], promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) }, stripVTControlCharacters: [Function: stripVTControlCharacters], toUSVString: [Function: toUSVString], transferableAbortSignal: [Getter], transferableAbortController: [Getter], aborted: [Getter], types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] }, parseEnv: [Function: parseEnv], parseArgs: [Function: parseArgs], TextDecoder: [class TextDecoder], TextEncoder: [class TextEncoder], MIMEType: [class MIMEType], MIMEParams: [class MIMEParams], diff: [Function: diff], setTraceSigInt: [Function: setTraceSigInt] }"
>
$ nvm use 25
Now using node v25.1.0 (npm v11.6.2)
$ node
Welcome to Node.js v25.1.0.
Type ".help" for more information.
> const util = require("node:util")
undefined
> util.inspect(util, { breakLength: Infinity })
"{ _errnoException: [Function: _errnoException], _exceptionWithHostPort: [Function: _exceptionWithHostPort], _extend: [Function: deprecated], callbackify: [Function: callbackify], debug: [Function: debuglog], debuglog: [Function: debuglog], deprecate: [Function: deprecate], format: [Function: format], styleText: [Function: styleText], formatWithOptions: [Function: formatWithOptions], getCallSites: [Function: getCallSites], getSystemErrorMap: [Function: getSystemErrorMap], getSystemErrorName: [Function: getSystemErrorName], getSystemErrorMessage: [Function: getSystemErrorMessage], inherits: [Function: inherits], inspect: [Function: inspect] { custom: Symbol(nodejs.util.inspect.custom), colors: [Object: null prototype] { reset: [Array], bold: [Array], dim: [Array], italic: [Array], underline: [Array], blink: [Array], inverse: [Array], hidden: [Array], strikethrough: [Array], doubleunderline: [Array], black: [Array], red: [Array], green: [Array], yellow: [Array], blue: [Array], magenta: [Array], cyan: [Array], white: [Array], bgBlack: [Array], bgRed: [Array], bgGreen: [Array], bgYellow: [Array], bgBlue: [Array], bgMagenta: [Array], bgCyan: [Array], bgWhite: [Array], framed: [Array], overlined: [Array], gray: [Array], redBright: [Array], greenBright: [Array], yellowBright: [Array], blueBright: [Array], magentaBright: [Array], cyanBright: [Array], whiteBright: [Array], bgGray: [Array], bgRedBright: [Array], bgGreenBright: [Array], bgYellowBright: [Array], bgBlueBright: [Array], bgMagentaBright: [Array], bgCyanBright: [Array], bgWhiteBright: [Array] }, styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: [Function], module: 'underline' }, replDefaults: [Getter/Setter] }, isArray: [Function: deprecated], isDeepStrictEqual: [Function: isDeepStrictEqual], promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) }, stripVTControlCharacters: [Function: stripVTControlCharacters], toUSVString: [Function: toUSVString], transferableAbortSignal: [Getter], transferableAbortController: [Getter], aborted: [Getter], types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] }, parseEnv: [Function: parseEnv], parseArgs: [Function: parseArgs], TextDecoder: [class TextDecoder], TextEncoder: [class TextEncoder], MIMEType: [class MIMEType], MIMEParams: [class MIMEParams], diff: [Function: diff], setTraceSigInt: [Function: setTraceSigInt] }"
> util.inspect(util, { breakLength: Infinity, depth: Infinity })
'{\n' +
  '  _errnoException: [Function: _errnoException],\n' +
  '  _exceptionWithHostPort: [Function: _exceptionWithHostPort],\n' +
  '  _extend: [Function: deprecated],\n' +
  '  callbackify: [Function: callbackify],\n' +
  '  debug: [Function: debuglog],\n' +
  '  debuglog: [Function: debuglog],\n' +
  '  deprecate: [Function: deprecate],\n' +
  '  format: [Function: format],\n' +
  '  styleText: [Function: styleText],\n' +
  '  formatWithOptions: [Function: formatWithOptions],\n' +
  '  getCallSites: [Function: getCallSites],\n' +
  '  getSystemErrorMap: [Function: getSystemErrorMap],\n' +
  '  getSystemErrorName: [Function: getSystemErrorName],\n' +
  '  getSystemErrorMessage: [Function: getSystemErrorMessage],\n' +
  '  inherits: [Function: inherits],\n' +
  '  inspect: [Function: inspect] {\n' +
  '    custom: Symbol(nodejs.util.inspect.custom),\n' +
  '    colors: [Object: null prototype] { reset: [ 0, 0 ], bold: [ 1, 22 ], dim: [ 2, 22 ], italic: [ 3, 23 ], underline: [ 4, 24 ], blink: [ 5, 25 ], inverse: [ 7, 27 ], hidden: [ 8, 28 ], strikethrough: [ 9, 29 ], doubleunderline: [ 21, 24 ], black: [ 30, 39 ], red: [ 31, 39 ], green: [ 32, 39 ], yellow: [ 33, 39 ], blue: [ 34, 39 ], magenta: [ 35, 39 ], cyan: [ 36, 39 ], white: [ 37, 39 ], bgBlack: [ 40, 49 ], bgRed: [ 41, 49 ], bgGreen: [ 42, 49 ], bgYellow: [ 43, 49 ], bgBlue: [ 44, 49 ], bgMagenta: [ 45, 49 ], bgCyan: [ 46, 49 ], bgWhite: [ 47, 49 ], framed: [ 51, 54 ], overlined: [ 53, 55 ], gray: [ 90, 39 ], redBright: [ 91, 39 ], greenBright: [ 92, 39 ], yellowBright: [ 93, 39 ], blueBright: [ 94, 39 ], magentaBright: [ 95, 39 ], cyanBright: [ 96, 39 ], whiteBright: [ 97, 39 ], bgGray: [ 100, 49 ], bgRedBright: [ 101, 49 ], bgGreenBright: [ 102, 49 ], bgYellowBright: [ 103, 49 ], bgBlueBright: [ 104, 49 ], bgMagentaBright: [ 105, 49 ], bgCyanBright: [ 106, 49 ], bgWhiteBright: [ 107, 49 ] },\n' +
  "    styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: [Function: highlightRegExp] { colors: [ 'green', 'red', 'yellow', 'cyan', 'magenta' ] }, module: 'underline' },\n" +
  '    replDefaults: [Getter/Setter]\n' +
  '  },\n' +
  '  isArray: [Function: deprecated],\n' +
  '  isDeepStrictEqual: [Function: isDeepStrictEqual],\n' +
  '  promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) },\n' +
  '  stripVTControlCharacters: [Function: stripVTControlCharacters],\n' +
  '  toUSVString: [Function: toUSVString],\n' +
  '  transferableAbortSignal: [Getter],\n' +
  '  transferableAbortController: [Getter],\n' +
  '  aborted: [Getter],\n' +
  '  types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] },\n' +
  '  parseEnv: [Function: parseEnv],\n' +
  '  parseArgs: [Function: parseArgs],\n' +
  '  TextDecoder: [class TextDecoder],\n' +
  '  TextEncoder: [class TextEncoder],\n' +
  '  MIMEType: [class MIMEType],\n' +
  '  MIMEParams: [class MIMEParams],\n' +
  '  diff: [Function: diff],\n' +
  '  setTraceSigInt: [Function: setTraceSigInt]\n' +
  '}'
How often does it reproduce? Is there a required condition?

Always reproducible when both breakLength and depth are set to Infinity.

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

According to the Node.js documentation:

breakLength <integer>
The length at which input values are split across multiple lines.
Set to Infinity to format the input as a single line (in combination with compact set to true or any number >= 1).
Default: 80.

Therefore, when breakLength is set to Infinity, the output should always be rendered as a single line, regardless of object depth or size.

What do you see instead?

The output contains multiple lines with indentation, even though breakLength is set to Infinity.

This happens only when depth is also set to Infinity.

Additional information

No response

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Empieza reproduciendo el ejemplo mínimo de util.inspect() en Node.js v24 y v25, tanto con breakLength: Infinity como con depth: Infinity. Rastrea la implementación de util.inspect() y la cobertura existente para estas opciones; se considera terminado cuando las opciones combinadas producen la salida esperada en una sola línea sin introducir regresiones en los demás casos descritos.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, nodejs
Área
backend
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.