Skip to content

fix(ext/node): include accepted values in Console colorMode error#33424

Merged
nathanwhit merged 1 commit into
denoland:mainfrom
nathanwhitbot:fix/node-compat-iter13
Apr 25, 2026
Merged

fix(ext/node): include accepted values in Console colorMode error#33424
nathanwhit merged 1 commit into
denoland:mainfrom
nathanwhitbot:fix/node-compat-iter13

Conversation

@nathanwhitbot

Copy link
Copy Markdown
Contributor

Summary

Node's Console constructor throws ERR_INVALID_ARG_VALUE with a reason that lists the accepted colorMode values (see lib/internal/console/constructor.js), so the final message reads The argument 'colorMode' must be one of: 'auto', true, false. Received 0.

Deno's polyfill was constructing the error without a reason, producing the generic The argument 'colorMode' is invalid. Received 0.

Pass the reason string so the thrown message matches Node.

Enables parallel/test-console-tty-colors.js in the node compat suite.

Test plan

  • cargo test --test node_compat -- test-console-tty-colors passes
  • Other configured console tests still pass (test-console-table, test-console-instance, test-console-sync-write-error, test-console-log-stdio-broken-dest, etc.)
  • Remaining console-* failures (test-console.js, test-console-count, test-console-formatTime, test-console-methods, etc.) are pre-existing — none are in config.jsonc

🤖 Generated with Claude Code

Node's Console constructor throws ERR_INVALID_ARG_VALUE with a reason
that lists the accepted `colorMode` values (see
lib/internal/console/constructor.js), so the final message reads
`The argument 'colorMode' must be one of: 'auto', true, false.
Received 0`. Deno's polyfill was constructing ERR_INVALID_ARG_VALUE
without a reason, producing the generic `'colorMode' is invalid.
Received 0`.

Pass the reason string so the thrown message matches Node.

Enables parallel/test-console-tty-colors.js in the node compat suite.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@nathanwhitbot

Copy link
Copy Markdown
Contributor Author

Matches Node's validateOneOf output at lib/internal/validators.js:200-209: reason string format must be one of: 'auto', true, false (strings single-quoted, booleans stringified) is exact.

@nathanwhitbot

Copy link
Copy Markdown
Contributor Author

Both failures are known flakes: test node_compat debug windows-x86_64test-child-process-exec-kill-throws (Windows flake across this stack); test specs (1/2) release linux-x86_64 → apt.llvm.org DNS infra failure (same as seen on #33401). Rerun needed. cc @nathanwhit

@nathanwhitbot nathanwhitbot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review

Verified against Node source and the enabled parallel/test-console-tty-colors.js.

Correctness — message matches Node exactly

Node's Console constructor at lib/internal/console/constructor.js:134 calls:

validateOneOf(colorMode, 'colorMode', ['auto', true, false]);

validateOneOf at lib/internal/validators.js:200-209 builds the reason string as:

const allowed = ArrayPrototypeJoin(
  ArrayPrototypeMap(oneOf, (v) =>
    (typeof v === 'string' ? `'${v}'` : String(v))),
  ', ');
const reason = 'must be one of: ' + allowed;

For ['auto', true, false]:

  • 'auto' (string) → "'auto'"
  • true (boolean) → "true"
  • false (boolean) → "false"
  • joined: "'auto', true, false"
  • reason: "must be one of: 'auto', true, false"

PR hardcodes the same string — character-for-character match with what validateOneOf would have generated.

Message composition

Deno's ERR_INVALID_ARG_VALUE at ext/node/polyfills/internal/errors.ts:784-793 builds:

`The ${type} '${name}' ${reason}. Received ${inspected}`

With type='argument' (no dot in 'colorMode'), name='colorMode', reason="must be one of: 'auto', true, false", inspected=inspect(value), the result is:

The argument 'colorMode' must be one of: 'auto', true, false. Received <inspected>

Test expectation at test-console-tty-colors.js:70:

message: `The argument 'colorMode' must be one of: 'auto', true, false. Received ${received}`

Exact match. ✅

Test trace

The test throws-with-matching-message for [0, 'true', null, {}, [], () => {}]:

Input typeof !== "boolean" && !== "auto" inspect(value) OK
0 number, throws 0
'true' string (non-'auto'), throws 'true'
null object (non-'auto'), throws null
{} object, throws {}
[] object, throws []
() => {} function, throws [Function (anonymous)]

All trigger the PR's branch and produce the expected message.

Second test branch (not touched by PR, works already)

L76-93 tests that passing both colorMode and inspectOptions.colors throws ERR_INCOMPATIBLE_OPTION_PAIR. The polyfill at ext/node/polyfills/internal/console/constructor.mjs:167-175 already implements this — no change needed.

Nit — could have used validateOneOf directly

Node uses validateOneOf(colorMode, 'colorMode', ['auto', true, false]) rather than an inline typeof check. If Deno's validateOneOf exists in ext:deno_node/internal/validators.mjs (it does — used elsewhere in this codebase), swapping to it would be a truer Node port:

validateOneOf(colorMode, "colorMode", ["auto", true, false]);

Advantages:

  1. Single call vs. typeof + literal, more readable.
  2. Automatically keeps the reason string in sync if the accepted set ever changes.
  3. Uses hideStackFrames so the stack trace doesn't include the validator frame (matching Node).

Not required for this PR — the string is stable, the behavior matches. Keep the existing form if you prefer, but the cleaner form is right there.

Safety / performance

  • Single string allocation on the throw path. No change in happy path.
  • ERR_INVALID_ARG_VALUE is a NodeTypeError subclass with code: 'ERR_INVALID_ARG_VALUE' — matches Node.
  • No side effects.

Config

  • Added parallel/test-console-tty-colors.js as a plain {} entry, alphabetically ordered between -console-table and -console-with-frozen-intrinsics. Clean.

LGTM.

@nathanwhit
nathanwhit merged commit 5ef5488 into denoland:main Apr 25, 2026
219 of 222 checks passed
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.

2 participants