Skip to content

util: inspect: do not crash on an Error stack pointing to itself #58196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

SamVerschueren
Copy link
Contributor

See #58195

This avoids a maximum call stack size exceeded crash when the error stack is pointing to the error itself error.stack = error. This bug was introduced by #56573.

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. util Issues and PRs related to the built-in util module. labels May 6, 2025
@SamVerschueren SamVerschueren changed the title util: inspect: do not crash on an Error stack pointing to the error itself util: inspect: do not crash on an Error stack pointing to itself May 6, 2025
@SamVerschueren SamVerschueren force-pushed the fix/inspect-cyclic-error-stack branch from 802e28b to 8b819f9 Compare May 6, 2025 16:02
Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

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

LGTM. I am just surprised the regular circular detection does not pick this up. Do we know why?

The output does seem to be better in this case, so it's likely a good idea not to have the circular check trigger.
Should we maybe just add additional information that it's circular? That might be useful for users?

@SamVerschueren
Copy link
Contributor Author

SamVerschueren commented May 6, 2025

Open to ideas on how to show the circularity. I think it's a good idea.

Copy link

codecov bot commented May 6, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.14%. Comparing base (e272637) to head (111b9ca).
Report is 327 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #58196      +/-   ##
==========================================
+ Coverage   90.13%   90.14%   +0.01%     
==========================================
  Files         630      637       +7     
  Lines      186780   188028    +1248     
  Branches    36653    36890     +237     
==========================================
+ Hits       168347   169504    +1157     
- Misses      11207    11279      +72     
- Partials     7226     7245      +19     
Files with missing lines Coverage Δ
lib/internal/util/inspect.js 99.96% <100.00%> (+<0.01%) ⬆️

... and 185 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@BridgeAR
Copy link
Member

BridgeAR commented May 6, 2025

@SamVerschueren instead of only returning the ErrorPrototypeToString call result, we could add additional information that the stack is circular similar to the other circular outputs.

@SamVerschueren
Copy link
Contributor Author

So I checked how it's done with objects where it looks like this

<ref *1> { bar: [Circular *1] }

The problem here though is that it's a method to get the stack string itself, so I don't see a way how to represent it in the same way more or less.

So I just tried some things out

in the case of the following code

const foo = new Error('foo'); 
foo.stack = foo; 

console.log(foo.stack);
  1. [[Circular] Error: foo]
  2. [<Circular> Error: foo]
  3. [[Circular stack] Error: foo]
  4. [<Circular stack> Error: foo]
  5. [[Circular *stack] Error: foo]
  6. [<Circular *stack> Error: foo]

Let me know what any one of you would like to see. Or something completely different, although might be a bit more work.

<ref *1> Error: foo { stack: [Circular *1] }

But this deviates way too much from what it was I feel like.

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

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

I had a brief look into this and it does not fully fix the problem.

There are currently two spots where we miss to add adding the circular check (the other spot is for weird function names), since we have to special handle parts of the inspection before getting to the spot where we add the object to our circular check (it is intentionally at that spot to prevent doing it for e.g., empty objects, arrays, etc.).

One of them is here. Just comparing for a simple direct recursion does not prevent other cases, for example:

const error = new Error()
const error2 = new Error()
error.stack = error2
error2.stack = error

@BridgeAR
Copy link
Member

@SamVerschueren could you take another look? :)

We could also land this as intermediate improvement and have another PR on top, I just thought it makes sense to combine the points that I looked at.

@SamVerschueren
Copy link
Contributor Author

Yes I'll definitely look into this. I was out this week so I'll probably do it over the weekend.

@BridgeAR
Copy link
Member

Ping @SamVerschueren

@SamVerschueren
Copy link
Contributor Author

Ugh Sorry. I totally forgot about this. I'll do it tomorrow!

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the PR!

@BridgeAR BridgeAR added the request-ci Add this label to start a Jenkins CI on a PR. label Jun 13, 2025
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jun 13, 2025
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

Copy link
Contributor

@Ethan-Arrowood Ethan-Arrowood left a comment

Choose a reason for hiding this comment

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

lgtm

@nodejs-github-bot
Copy link
Collaborator

@BridgeAR BridgeAR added commit-queue Add this label to land a pull request using GitHub Actions. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels Jun 16, 2025
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Jun 16, 2025
@nodejs-github-bot nodejs-github-bot merged commit ea5d37e into nodejs:main Jun 16, 2025
64 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in ea5d37e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. needs-ci PRs that need a full CI run. util Issues and PRs related to the built-in util module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants