fix: log full error object in logerror (fixes #6462)#7290
fix: log full error object in logerror (fixes #6462)#7290myselfsiddharth wants to merge 2 commits into
Conversation
|
cc @Nitin-Mohapatra — happy to help rebase #6464 or fold this test into that PR if maintainers prefer a single PR. |
Ap-0007
left a comment
There was a problem hiding this comment.
This is a very clean and necessary improvement! Passing the raw error object directly to console.error leverages Node's built-in error inspection (especially with standard Error.cause support since Node 18).
One minor suggestion to make the added test more robust:
In test/app.logerror.js, console.error is mocked inline inside the test case and restored inside the async callbacks:
var logged
var original = console.error
console.error = function (err) {
logged = err
}
...If the HTTP request or test times out, or if an unexpected exception occurs before the callbacks are executed, console.error might not be restored, potentially leaking the mock to other tests in the runner.
To ensure global state is always restored, we can use Mocha's standard beforeEach/afterEach hooks:
describe('logerror', function () {
var original
beforeEach(function () {
original = console.error
})
afterEach(function () {
if (original) {
console.error = original
}
})
it('should log the full error object', function (done) {
var app = express()
app.set('env', 'development')
var logged
console.error = function (err) {
logged = err
}
app.use(function (req, res, next) {
var inner = new Error('inner')
next(new Error('outer', { cause: inner }))
})
request(app)
.get('/')
.expect(500, function (err) {
if (err) return done(err)
setImmediate(function () {
assert.ok(logged instanceof Error)
assert.strictEqual(logged.message, 'outer')
assert.ok(logged.cause instanceof Error)
assert.strictEqual(logged.cause.message, 'inner')
done()
})
})
})
})This guarantees cleanup regardless of whether the assertions pass or the test times out.
|
Good catch, @Ap-0007 |
Use console.error(err) instead of err.stack || err.toString() so Node's built-in error inspection includes Error.cause, custom properties (e.g. Sequelize parent/original), and AggregateError details. Adds regression test for the default error handler logging path. Fixes expressjs#6462 Related: expressjs#6464 (same one-line fix; this PR adds test coverage and is rebased on current master)
83da617 to
6263c0d
Compare
Summary
Changes
logerrorinlib/application.jsto useconsole.error(err)instead ofconsole.error(err.stack || err.toString()), so Node's built-in error inspection preservesError.cause, custom enumerable properties (e.g. Sequelizeparent/original), andAggregateErrordetails.This matches the approach in #6464 (approved in review; vestigial
err.stackworkaround from pre-Node-18 whenconsole.error(err)did not print stacks). Express 5 already requires Node >= 18.This PR is rebased on current
masterand adds regression test coverage (test/app.logerror.js) for the default error handler logging path.Fixes #6462
Related PRs
Test plan
npm test -- test/app.logerror.jsnpm test(1250 passing)Behavior note
Only affects stderr when the default error handler runs and
env !== 'test'. HTTP responses are unchanged.