Skip to content
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

Asserts (and probably other Bounce.isSystem) loose stack trace #4531

Open
legraphista opened this issue Oct 18, 2024 · 1 comment
Open

Asserts (and probably other Bounce.isSystem) loose stack trace #4531

legraphista opened this issue Oct 18, 2024 · 1 comment
Labels
bug Bug or defect

Comments

@legraphista
Copy link

legraphista commented Oct 18, 2024

Runtime

node.js

Runtime version

22.9.0

Module version

@hapi/[email protected]

Last module version without issue

unknown

Used with

standalone

Any other relevant information

When throwing an unhandled exception, the stack is available in the boom object in onPreResponse, but not for "system" exceptions like AssertionError


Culprit:

response = Boom.badImplementation(err);

The error is passed as message instead of data

https://github.com/hapijs/boom/blob/01a4996dc6e62949aa7a98ca75b2d0dcd8a4a0a8/lib/index.js#L74
Boom catches it as error, but Hoek.clone loses the stack trace ❗

> messageOrError.stack
'AssertionError [ERR_ASSERTION]: Hello World
    at handler (/home/stefan/[redacted]/src/index.ts:26:9)
    at exports.Manager.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/toolkit.js:57:29)
    at internals.handler (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:370:68)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:280:9)'
> Hoek.clone(messageOrError).stack
undefined

https://github.com/hapijs/hoek/blob/0f0a14eae94d28b4826e3bb4b2071b4eccbd398f/lib/clone.js#L91-L94
when key === 'stack', the descriptor is retrieved and applied to newObj, but descriptor.get() is undefined

> Object.getOwnPropertyDescriptor(new Error('hello'), 'stack').get()
undefined

What are you trying to achieve or the steps to reproduce?

export const hapiServer = new Server({
    port: 3000,
    address: "0.0.0.0"
});

hapiServer.ext('onPreResponse', (request, h) => {
    const response = request.response;
    if (response instanceof Error) {
        console.error(request.info.id, response);
    }
    return h.continue;
});

hapiServer.route({
    method: 'GET',
    path: '/assert',
    handler: (request, h) => {
        assert(false, 'Hello World');
    }
});

hapiServer.route({
    method: 'GET',
    path: '/throw',
    handler: (request, h) => {
        throw new Error('Hello World');
    }
});

await hapiServer.start()

What was the result you got?

curl 127.0.0.1:3000/assert

1729274024376:something:416933:m2f13fpr:10000 [AssertionError: Hello World] {
  generatedMessage: false,
  code: 'ERR_ASSERTION',
  actual: false,
  expected: true,
  operator: '==',
  isBoom: true,
  isServer: true,
  data: null,
  output: [Object],
  isDeveloperError: true
}
curl localhost:3000/throw

1729274081766:something:416933:m2f13fpr:10001 Error: Hello World
    at handler (/home/stefan/[redacted]/src/index.ts:34:15)
    at exports.Manager.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/toolkit.js:57:29)
    at internals.handler (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:370:68)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:280:9) {
  isBoom: true,
  isServer: true,
  data: null,
  output: {
    statusCode: 500,
    payload: {
      statusCode: 500,
      error: 'Internal Server Error',
      message: 'An internal server error occurred'
    },
    headers: {}
  }
}

What result did you expect?

curl 127.0.0.1:3000/assert

1729274228005:something:419617:m2f183s8:10000 AssertionError [ERR_ASSERTION]: Hello World
    at handler (/home/stefan/[redacted]/src/index.ts:26:9)
    at exports.Manager.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/toolkit.js:57:29)
    at internals.handler (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:370:68)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:280:9) {
  generatedMessage: false,
  code: 'ERR_ASSERTION',
  actual: false,
  expected: true,
  operator: '==',
  isBoom: true,
  isServer: true,
  data: null,
  output: [Object]
}
curl localhost:3000/throw

1729274081766:something:416933:m2f13fpr:10001 Error: Hello World
    at handler (/home/stefan/[redacted]/src/index.ts:34:15)
    at exports.Manager.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/toolkit.js:57:29)
    at internals.handler (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:370:68)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._execute (/home/stefan/[redacted]/node_modules/@hapi/hapi/lib/request.js:280:9) {
  isBoom: true,
  isServer: true,
  data: null,
  output: {
    statusCode: 500,
    payload: {
      statusCode: 500,
      error: 'Internal Server Error',
      message: 'An internal server error occurred'
    },
    headers: {}
  }
}
@legraphista legraphista added the bug Bug or defect label Oct 18, 2024
@kanongil
Copy link
Contributor

kanongil commented Oct 19, 2024

Thanks for the report. This is a known issue with Hoek.clone() and node v21+. I have proposed a fix in hapijs/hoek#390, and made an issue against hapi in #4519.

Until this is fixed, I would suggest you use node 20 for running hapi.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug or defect
Projects
None yet
Development

No branches or pull requests

2 participants