Skip to content

Scopes are leaking in NestJS requests #15940

Closed

Description

@sagrawal31

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nestjs

SDK Version

9.10.1

Framework Version

Nest 10.3.10

Link to Sentry event

No response

Reproduction Example/SDK Setup

No response

Steps to Reproduce

  1. Create a NestJS app.
  2. Add a controller with a simple log.
  3. Add a NestJS interceptor which sets tags/context/user conditionally (maybe based on some header/authentication).
  4. Hit the first request, which should set some tag/context/user.
  5. Hit the second request, which should not set any request and log an error to Sentry.

Expected Result

The tracked should not have any custom tag/context or user.

Actual Result

The tracked error have the tags/context/user from the previous request.

Activity

  1. added theissue type on Apr 1, 2025
  2. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Apr 1, 2025
  3. changed the title [-]Scopes are leaking[/-] [+]Scopes are leaking in NestJS requests[/+] on Apr 1, 2025
  4. sagrawal31 commented on Apr 1, 2025

    @sagrawal31
    Author

    I'm trying to reproduce this on a fresh NestJS project and couldn't reproduce it. Please don't spend time on it yet. Will keep you updated.

  5. Lms24 commented on Apr 1, 2025

    @Lms24
    Member

    Hey @sagrawal31 thanks for letting us know! I'll close this issue for now to maintain a clean issue feed but please feel free to ping me whenever you have a working reproduction and then we'll reopen this. Thanks!

  6. sagrawal31 commented on Apr 4, 2025

    @sagrawal31
    Author

    Thank you @Lms24. I spent my last 2 days converting my test NestJS project as similar (like wrapping to promise, calling Sentry at almost the same places, etc.) to our production code, but it wasn't helping.

    So, I took a different approach. I started removing modules and code one by one from our vast production code and started testing the leak, and I'm glad I succeeded. Here is a fresh NestJS code to reproduce the same: https://github.com/letscooee/nestjs-sentry-test

    Steps to reproduce

    1. Clone the repo git clone https://github.com/letscooee/nestjs-sentry-test.git
    2. Set an environment variable SENTRY_DSN or modify sentry.service.ts directly for the DSN.
    3. Run npm run start:dev and server should be up at 3000 port.
    4. Run the following requests:
    # /foo endpoint will set a tag and user and capture an "Error1" issue on Sentry
    curl --header "content-type: application/json" http://localhost:3000/foo
    
    # /bar endpoint will not set any tags and user and capture an "Error2" issue on Sentry
    curl --header "content-type: application/json" http://localhost:3000/bar
    

    Expected behaviour

    The second request should not leak on the Sentry request
    Image

    Actual behaviour

    The tag and user are leaking to the second request as well.
    Image

    Workaround I figured

    Wrapping the SentryInterceptor#intercept method code with return Sentry.withIsolationScope(async () => {}) makes it work.

    Actual fix that I don't understand

    If you check my last commit (letscooee/nestjs-sentry-test@2a99b2f), I moved the Sentry.init code from main.ts initialisation to the constructor initialisation of SentryService. Because of this change, the scope started to leak in the requests. The point I didn't understand is that fundamentally, Sentry is being initialised at a later point of time that's the only difference, so why does the request isolation start breaking? That's where I need your expertise.

  7. reopened this on Apr 4, 2025
  8. Lms24 commented on Apr 4, 2025

    @Lms24
    Member

    Hey @sagrawal31 thanks a lot for the great reproduction! I was able to reproduce it instantly.

    You already correctly identified that you get scope leakage because of Sentry initializing too late in the game. Unfortunately, this is expected behaviour or rather, an unfortunate consequence of how OpenTelemetry instruments NodeJS applications.

    Fundamentally the thing that's failing is that our SDK (or the Otel SDK under the hood) needs to instrument node:http(s). We do this to capture request spans but even more importantly to isolate requests, more specifically to set an isolation scope as you did in your workaround.

    To instrument libraries like http the SDK basically intercepts require('http') calls. To do that, it needs to be initialized before the first such require call. If you move the Sentry.init code to your service, this is too late as the NestJS server is already setting up (afaik by default an Express server which internally uses http).

    That's the reason why our docs clearly state that the SDK must be initialized first thing in your main.ts file. I hope this makes sense.

    Note, if you're transpiling to ESM (i.e. your built code has import statements instead of require calls) make sure to follow these instructions instead.

  9. removed theissue type on Apr 4, 2025
  10. self-assigned this
    on Apr 4, 2025
  11. 1 remaining item

  12. Lms24 commented on Apr 4, 2025

    @Lms24
    Member

    So to conclude, this isn't a bug but unfortunate, expected behaviour. I recommend following our docs for setup and avoiding a late-init of Sentry. If you cannot at all avoid this, there's a compromise to preload the instrumentation part of the SDK and only init the SDK itself later. Follow this guide for it.

    Let me know if you have any other questions.

  13. moved this from Waiting for: Product Owner to Waiting for: Community in GitHub Issues with 👀 3on Apr 4, 2025
  14. mydea commented on Apr 7, 2025

    @mydea
    Member

    I created an issue to see if we can warn for this case better in the SDK: #15986

  15. sagrawal31 commented on Apr 7, 2025

    @sagrawal31
    Author

    Hi @Lms24, apologies for not replying immediately. I read your comments right after you posted and I went testing out something else.

    Thank you for testing my test repository and reverting back with the detailed investigation, screenshot, and amazing explanation. I loved how dedicated you are to your work. I showed your comments to my team members as well (@AbhishekTaparia @ashishgkwd534). They are much appreciated!

    And how silly I was to miss the part of patching the http(s) which would not be possible if the SDK is being initialised lately. That first mention of http patching cleared my mind. Thanks a lot!

    Also, how did you enable the Sentry logging? I tried to do it myself with the debug flag while investigating.

  16. moved this from Waiting for: Community to Waiting for: Product Owner in GitHub Issues with 👀 3on Apr 7, 2025
  17. Lms24 commented on Apr 7, 2025

    @Lms24
    Member

    Hey @sagrawal31 thanks for the kind words, appreciate them a lot! And please, no need to apologize, we get this question a lot. Your example was just perfect to explain things in detail :)

    Also, how did you enable the Sentry logging? I tried to do it myself with the debug flag while investigating.

    Sentry.init({
      // your other options, dsn, etc..
      debug: true,
    })

    In some SDKs, you might need to specifically enabled debug output bundling (e.g. Nett.js) but for @sentry/nestjs this should be enough and it's exactly what I did.

    I'm going to close this issue because I believe everything was answered (and improving debug logging was extracted to #15986). Please let me know if you have more questions, happy to help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions