fix(ext/node): include accepted values in Console colorMode error#33424
Conversation
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]>
|
Matches Node's |
|
Both failures are known flakes: |
nathanwhitbot
left a comment
There was a problem hiding this comment.
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:
- Single call vs. typeof + literal, more readable.
- Automatically keeps the reason string in sync if the accepted set ever changes.
- Uses
hideStackFramesso 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_VALUEis aNodeTypeErrorsubclass withcode: 'ERR_INVALID_ARG_VALUE'— matches Node.- No side effects.
Config
- Added
parallel/test-console-tty-colors.jsas a plain{}entry, alphabetically ordered between-console-tableand-console-with-frozen-intrinsics. Clean.
LGTM.
Summary
Node's Console constructor throws
ERR_INVALID_ARG_VALUEwith a reason that lists the acceptedcolorModevalues (seelib/internal/console/constructor.js), so the final message readsThe 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.jsin the node compat suite.Test plan
cargo test --test node_compat -- test-console-tty-colorspassestest-console-table,test-console-instance,test-console-sync-write-error,test-console-log-stdio-broken-dest, etc.)test-console.js,test-console-count,test-console-formatTime,test-console-methods, etc.) are pre-existing — none are inconfig.jsonc🤖 Generated with Claude Code