Repository navigation
util.inspect throws when given a ZodError #60717
Description
Activity
Given code to reproduce works fine in version
v26.0.0-pre@siaeyy I can reproduce it with the mentioned zod version.
@siaeyy I can reproduce it with the mentioned zod version.
Sorry, I was using the latest version of zod
- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.utilIssues and PRs related to the built-in util module.Issues and PRs related to the built-in util module.
on Nov 15, 2025 So the root cause is that the zod error has an
errorsproperty that is not an own property.With the change there are two properties were this could happen:
causeanderrorson errors. All other properties behave regularly and would not need a different handling. It is not an issue for most errors, since they would have these as own non-enumerable properties.The best fix I could think of right now is adding this right after the
desc ??= ObjectGetOwnPropertyDescriptor(value, key)in theformatProperty()method:while (desc === undefined) { value = ObjectGetPrototypeOf(value); desc = ObjectGetOwnPropertyDescriptor(value, key); }
That way it will have the correct enumerability and show that it is a getter. That would otherwise not be possible.
I am just not happy that we seemingly have to add a special handling there just for these two properties.
@mnahkies @siaeyy would one of you be willing to open a PR with that change and adding a regression test for both mentioned properties?
Of course I am willing to open a PR :)
It will actually be possible to handle it in a different spot as well by using the newly introduced extraKeys. The handler for those could than loop through the prototypes as described. That way the loop is only used in case extra keys are needed, which is a rarer case. This will however not have a real impact on the performance, due to the insignificance of the check compared to the rest of the algorithm. It just feels cleaner, due to also not having to manipulate the keys in those places anymore. The downside is that the main method will become even bigger than before.
I think here is a example of different spot:
node/lib/internal/util/inspect.js
Lines 1958 to 1972 in 4a868fd
if ('cause' in err && (keys.length === 0 || !ArrayPrototypeIncludes(keys, 'cause'))) { ArrayPrototypePush(keys, 'cause'); } // Print errors aggregated into AggregateError try { const errors = err.errors; if (ArrayIsArray(errors) && (keys.length === 0 || !ArrayPrototypeIncludes(keys, 'errors'))) { ArrayPrototypePush(keys, 'errors'); } } catch { // If errors is a getter that throws, we ignore the error. } @siaeyy I am not sure I follow. That code is the root cause of the problem, correct. It adds keys that have to be handled, while not knowing who the owning object is. That is why I named these two properties above :)
Reacted by siaeyy- marked console.error crashes in 24.11.1 when logging Error objects with getters #60948 as a duplicate of this issue
on Dec 4, 2025 This just broke our tests after a Node upgrade. ("fortunately", otherwise this would have badly failed in production)
consolelogging methods failing in this manner is... very bad, as they should never throw an exception – these are quite often used in places eg. error handlers themselves, in which throwing another exception can cause a catastrophic failure (with possible permanent state corruption).I'd suggest looking into adding a general error boundary for console methods, as that's the software engineering best practice for situations like these.
- added a commit that references this issue
on Dec 22, 2025 - added 2 commits that reference this issue
on Jan 9, 2026 - added a commit that references this issue
on Jan 13, 2026 @aduh95, it seems that the fix hasn't been included in v24 yet. Will the fix get included in v24 soon? This bug prevents people from updating to the latest version, which is particularly important now that multiple vulnerabilities were fixed in the latest release yesterday.
Reacted by Louis Trezzini, Luke Stevens, Kareem Daggash, Adrian Falleiro, Michael Nahkies, Pierre-Luc Paour, Shawn McKnight, studds, Alexandre Djerbetian, Damien Pobel and 3 more- added a commit that references this issue
on Jan 19, 2026
Version
v24.11.1
Platform
Subsystem
util
What steps will reproduce the bug?
Using
zod@3.25.76How often does it reproduce? Is there a required condition?
Seems to happen on any
ZodErrorWhat is the expected behavior? Why is that the expected behavior?
It should inspect the error, same as it did on Node v22
What do you see instead?
Exception.
Additional information
I believe this is a regression caused by 748d4f6 - based on the timing / line numbers.