Repository: getsentry/sentry-python

Issue:
ValueError: I/O operation on closed file
### How do you use Sentry?

Self-hosted/on-premise

### Version

1.31.0

### Steps to Reproduce

I use sentry in a Python 3.11, Django/Channels/Celery/Docker application. This issue pops up when I refresh my web pages. These pages may or may not have a websocket connection (channels) and do not kick off any celery task when loaded. The application runs in a docker container using the system (container) python interpreter. (It does not matter if the interpreter is in a venv or the system). I use poetry to manage my dependencies, which are listed below.

Weirdly enough, I have another identical setup for another project and I do not encounter this issue. In fact, I copy-pasted the sentry settings from that project to this one and have not modified them except for the DSN. The only real difference between that one and this one is the other is using Django 4.0.x, whereas this project is using Django 4.2.x.

This is a development environment, so therefore I am using `python manage.py runserver 0.0.0.0:8000` through VSCode's debugger in a devcontainer.

```python
alabaster==0.7.13
amqp==5.1.1
anyio==4.0.0
argon2-cffi==21.3.0
argon2-cffi-bindings==21.2.0
asgiref==3.7.2
astroid==2.15.6
asttokens==2.4.0
attrs==23.1.0
autobahn==23.6.2
Automat==22.10.0
Babel==2.12.1
backcall==0.2.0
beautifulsoup4==4.12.2
billiard==4.1.0
black==23.9.1
blinker==1.6.2
Brotli==1.1.0
celery==5.3.4
certifi==2023.7.22
cffi==1.15.1
cfgv==3.4.0
channels==4.0.0
channels-redis==4.1.0
charset-normalizer==3.2.0
click==8.1.7
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.3.0
colorama==0.4.6
ConfigArgParse==1.7
constantly==15.1.0
coverage==7.3.1
crispy-bootstrap5==0.7
cron-descriptor==1.4.0
cryptography==41.0.3
cssbeautifier==1.14.9
daphne==4.0.0
decorator==5.1.1
defusedxml==0.7.1
detect-secrets==1.4.0
dill==0.3.7
distlib==0.3.7
Django==4.2.5
django-allauth==0.54.0
django-appconf==1.0.5
django-celery-beat==2.5.0
django-compressor==4.4
django-cors-headers==4.2.0
django-coverage-plugin==3.1.0
django-crispy-forms==2.0
django-debug-toolbar==4.2.0
django-environ==0.10.0
django-extensions==3.2.3
django-filter==23.2
django-macros==0.4.0
django-model-utils==4.3.1
django-polymorphic==3.1.0
django-redis==5.3.0
django-stubs==4.2.4
django-stubs-ext==4.2.2
django-timezone-field==6.0.1
djangorestframework==3.14.0
djangorestframework-stubs==3.14.2
djlint==1.32.1
docutils==0.20.1
drf-spectacular==0.26.4
drf-spectacular-sidecar==2023.9.1
EditorConfig==0.12.3
executing==1.2.0
factory-boy==3.3.0
Faker==19.6.1
filelock==3.12.4
flake8==6.1.0
flake8-isort==6.0.0
Flask==2.3.3
Flask-BasicAuth==0.2.0
Flask-Cors==4.0.0
flower==2.0.1
furo==2023.9.10
gevent==23.9.1
geventhttpclient==2.0.10
greenlet==3.0.0rc3
gunicorn==21.2.0
h11==0.14.0
hiredis==2.2.3
html-tag-names==0.1.2
html-void-elements==0.1.0
httptools==0.6.0
humanize==4.8.0
hyperlink==21.0.0
hypothesis==6.84.3
identify==2.5.28
idna==3.4
imagesize==1.4.1
incremental==22.10.0
inflection==0.5.1
iniconfig==2.0.0
ipdb==0.13.13
ipython==8.15.0
isort==5.12.0
itsdangerous==2.1.2
jedi==0.19.0
Jinja2==3.1.2
jsbeautifier==1.14.9
json5==0.9.14
jsonschema==4.19.0
jsonschema-specifications==2023.7.1
kombu==5.3.2
lazy-object-proxy==1.9.0
livereload==2.6.3
locust==2.16.1
loguru==0.7.2
MarkupSafe==2.1.3
matplotlib-inline==0.1.6
mccabe==0.7.0
msgpack==1.0.5
mssql-django==1.3
mypy==1.5.1
mypy-extensions==1.0.0
nodeenv==1.8.0
numpy==1.25.2
oauthlib==3.2.2
packaging==23.1
parso==0.8.3
pathspec==0.11.2
pexpect==4.8.0
pickleshare==0.7.5
Pillow==10.0.1
pip==23.2.1
platformdirs==3.10.0
pluggy==1.3.0
pre-commit==3.4.0
prometheus-client==0.17.1
prompt-toolkit==3.0.39
psutil==5.9.5
ptyprocess==0.7.0
pure-eval==0.2.2
py==1.11.0
pyasn1==0.5.0
pyasn1-modules==0.3.0
pycodestyle==2.11.0
pycparser==2.21
pyflakes==3.1.0
Pygments==2.16.1
PyJWT==2.8.0
pylint==2.17.5
pylint-celery==0.3
pylint-django==2.5.3
pylint-plugin-utils==0.8.2
pyodbc==4.0.39
pyOpenSSL==23.2.0
pytest==7.4.2
pytest-django==4.5.2
pytest-sugar==0.9.7
python-crontab==3.0.0
python-dateutil==2.8.2
python-dotenv==1.0.0
python-slugify==8.0.1
python3-openid==3.2.0
pytz==2023.3.post1
PyYAML==6.0.1
pyzmq==25.1.1
rcssmin==1.1.1
redis==4.6.0
referencing==0.30.2
regex==2023.8.8
requests==2.31.0
requests-oauthlib==1.3.1
rjsmin==1.2.1
roundrobin==0.0.4
rpds-py==0.10.3
sentry-sdk==1.31.0
service-identity==23.1.0
setuptools==68.2.2
six==1.16.0
sniffio==1.3.0
snowballstemmer==2.2.0
sortedcontainers==2.4.0
soupsieve==2.5
Sphinx==7.2.6
sphinx-autobuild==2021.3.14
sphinx-basic-ng==1.0.0b2
sphinxcontrib-applehelp==1.0.7
sphinxcontrib-devhelp==1.0.5
sphinxcontrib-htmlhelp==2.0.4
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.6
sphinxcontrib-serializinghtml==1.1.9
sqlparse==0.4.4
stack-data==0.6.2
termcolor==2.3.0
text-unidecode==1.3
tomlkit==0.12.1
tornado==6.3.3
tox==3.28.0
tqdm==4.66.1
traitlets==5.10.0
Twisted==23.8.0
txaio==23.1.1
types-pytz==2023.3.0.1
types-PyYAML==6.0.12.11
types-requests==2.31.0.2
types-urllib3==1.26.25.14
typing_extensions==4.7.1
tzdata==2023.3
uritemplate==4.1.1
urllib3==2.0.4
uvicorn==0.23.2
uvloop==0.17.0
vine==5.0.0
virtualenv==20.24.5
watchdog==3.0.0
watchfiles==0.19.0
wcwidth==0.2.6
websockets==11.0.3
Werkzeug==2.3.7
wheel==0.41.2
whitenoise==6.5.0
wrapt==1.15.0
zope.event==5.0
zope.interface==6.0
```
(My application is also listed here as an editable install, I removed it for ease of copy-paste)

### Expected Result

Not an error.

### Actual Result

Here is the stacktrace, graciously provided by loguru, from the start of the request until it finishes:

```python
HTTP GET /dashboard/ 200 [0.01, 172.21.0.11:33932]
2023-09-15 10:03:50.689 | DEBUG    | logging:callHandlers:1706 - HTTP 200 response started for ['172.21.0.11', 33932]
2023-09-15 10:03:50.689 | DEBUG    | logging:callHandlers:1706 - HTTP close for ['172.21.0.11', 33932]
2023-09-15 10:03:50.690 | DEBUG    | logging:callHandlers:1706 - HTTP response complete for ['172.21.0.11', 33932]
2023-09-15 10:03:50.690 | INFO     | logging:callHandlers:1706 - HTTP GET /dashboard/ 200 [0.01, 172.21.0.11:33932]
2023-09-15 10:03:50.691 | ERROR    | logging:callHandlers:1706 - Internal error in sentry_sdk
Traceback (most recent call last):

  File "/usr/local/lib/python3.11/threading.py", line 995, in _bootstrap
    self._bootstrap_inner()
    │    └ <function Thread._bootstrap_inner at 0x7f5648be6480>
    └ <Thread(django-main-thread, started daemon 140008135292672)>
  File "/usr/local/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    self.run()
    │    └ <function Thread.run at 0x7f562f4aeac0>
    └ <Thread(django-main-thread, started daemon 140008135292672)>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/threading.py", line 70, in run
    return old_run_func(self, *a, **kw)
           │            │      │    └ {}
           │            │      └ ()
           │            └ <Thread(django-main-thread, started daemon 140008135292672)>
           └ <function Thread.run at 0x7f5648be6160>
  File "/usr/local/lib/python3.11/threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
    │    │        │    │        │    └ {'verbosity': 1, 'settings': None, 'pythonpath': None, 'traceback': False, 'no_color': False, 'force_color': False, 'addrport...
    │    │        │    │        └ <Thread(django-main-thread, started daemon 140008135292672)>
    │    │        │    └ ()
    │    │        └ <Thread(django-main-thread, started daemon 140008135292672)>
    │    └ <function Command.inner_run at 0x7f562f4ae980>
    └ <Thread(django-main-thread, started daemon 140008135292672)>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
    │   │       └ {'verbosity': 1, 'settings': None, 'pythonpath': None, 'traceback': False, 'no_color': False, 'force_color': False, 'addrport...
    │   └ ()
    └ <bound method Command.inner_run of <whitenoise.runserver_nostatic.management.commands.runserver.Command object at 0x7f563f913...
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/daphne/management/commands/runserver.py", line 135, in inner_run
    ).run()
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/daphne/server.py", line 149, in run
    reactor.run(installSignalHandlers=self.signal_handlers)
    │       │                         │    └ False
    │       │                         └ <daphne.server.Server object at 0x7f562e7a3ed0>
    │       └ <function AsyncioSelectorReactor.run at 0x7f564474b6a0>
    └ <twisted.internet.asyncioreactor.AsyncioSelectorReactor object at 0x7f5644a202d0>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/twisted/internet/asyncioreactor.py", line 255, in run
    self._asyncioEventloop.run_forever()
    │    │                 └ <function BaseEventLoop.run_forever at 0x7f56486a23e0>
    │    └ <_UnixSelectorEventLoop running=True closed=False debug=False>
    └ <twisted.internet.asyncioreactor.AsyncioSelectorReactor object at 0x7f5644a202d0>
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 607, in run_forever
    self._run_once()
    │    └ <function BaseEventLoop._run_once at 0x7f56486a4220>
    └ <_UnixSelectorEventLoop running=True closed=False debug=False>
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1922, in _run_once
    handle._run()
    │      └ <function Handle._run at 0x7f56485d11c0>
    └ <Handle Task.task_wakeup(<Future finished result=None>)>
  File "/usr/local/lib/python3.11/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
    │    │            │    │           │    └ <member '_args' of 'Handle' objects>
    │    │            │    │           └ <Handle Task.task_wakeup(<Future finished result=None>)>
    │    │            │    └ <member '_callback' of 'Handle' objects>
    │    │            └ <Handle Task.task_wakeup(<Future finished result=None>)>
    │    └ <member '_context' of 'Handle' objects>
    └ <Handle Task.task_wakeup(<Future finished result=None>)>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/django/contrib/staticfiles/handlers.py", line 101, in __call__
    return await self.application(scope, receive, send)
                 │    │           │      │        └ functools.partial(<bound method Server.handle_reply of <daphne.server.Server object at 0x7f562e7a3ed0>>, <WebRequest at 0x7f5...
                 │    │           │      └ <bound method Queue.get of <Queue at 0x7f562c25d7d0 maxsize=0 _queue=[{'type': 'http.disconnect'}] tasks=2>>
                 │    │           └ {'type': 'http', 'http_version': '1.0', 'method': 'GET', 'path': '/dashboard/', 'raw_path': b'/dashboard/', 'root_path': '', ...
                 │    └ <channels.routing.ProtocolTypeRouter object at 0x7f562e62bdd0>
                 └ <django.contrib.staticfiles.handlers.ASGIStaticFilesHandler object at 0x7f562e7a3f50>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/channels/routing.py", line 62, in __call__
    return await application(scope, receive, send)
                 │           │      │        └ functools.partial(<bound method Server.handle_reply of <daphne.server.Server object at 0x7f562e7a3ed0>>, <WebRequest at 0x7f5...
                 │           │      └ <bound method Queue.get of <Queue at 0x7f562c25d7d0 maxsize=0 _queue=[{'type': 'http.disconnect'}] tasks=2>>
                 │           └ {'type': 'http', 'http_version': '1.0', 'method': 'GET', 'path': '/dashboard/', 'raw_path': b'/dashboard/', 'root_path': '', ...
                 └ <django.core.handlers.asgi.ASGIHandler object at 0x7f5646202450>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/django/asgi.py", line 40, in sentry_patched_asgi_handler
    return await middleware(scope, receive, send)
                 │          │      │        └ functools.partial(<bound method Server.handle_reply of <daphne.server.Server object at 0x7f562e7a3ed0>>, <WebRequest at 0x7f5...
                 │          │      └ <bound method Queue.get of <Queue at 0x7f562c25d7d0 maxsize=0 _queue=[{'type': 'http.disconnect'}] tasks=2>>
                 │          └ {'type': 'http', 'http_version': '1.0', 'method': 'GET', 'path': '/dashboard/', 'raw_path': b'/dashboard/', 'root_path': '', ...
                 └ <bound method SentryAsgiMiddleware._run_asgi3 of <sentry_sdk.integrations.asgi.SentryAsgiMiddleware object at 0x7f562c1f8cc0>>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/asgi.py", line 146, in _run_asgi3
    return await self._run_app(scope, receive, send, asgi_version=3)
                 │    │        │      │        └ functools.partial(<bound method Server.handle_reply of <daphne.server.Server object at 0x7f562e7a3ed0>>, <WebRequest at 0x7f5...
                 │    │        │      └ <bound method Queue.get of <Queue at 0x7f562c25d7d0 maxsize=0 _queue=[{'type': 'http.disconnect'}] tasks=2>>
                 │    │        └ {'type': 'http', 'http_version': '1.0', 'method': 'GET', 'path': '/dashboard/', 'raw_path': b'/dashboard/', 'root_path': '', ...
                 │    └ <function SentryAsgiMiddleware._run_app at 0x7f5646b93ce0>
                 └ <sentry_sdk.integrations.asgi.SentryAsgiMiddleware object at 0x7f562c1f8cc0>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/asgi.py", line 211, in _run_app
    with hub.start_transaction(
         │   └ <function Hub.start_transaction at 0x7f56475b0e00>
         └ <sentry_sdk.hub.Hub object at 0x7f562c23a910>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/tracing.py", line 614, in __exit__
    super(Transaction, self).__exit__(ty, value, tb)
          │            │              │   │      └ None
          │            │              │   └ None
          │            │              └ None
          │            └ <Transaction(name='/dashboard/', op='http.server', trace_id='1c8c9c6d7abc42b4b2b58ef2ae9f9bc5', span_id='87b885f27515d8ae', p...
          └ <class 'sentry_sdk.tracing.Transaction'>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/tracing.py", line 201, in __exit__
    self.finish(hub)
    │    │      └ <sentry_sdk.hub.Hub object at 0x7f562c23a910>
    │    └ <function Transaction.finish at 0x7f56479c2f20>
    └ <Transaction(name='/dashboard/', op='http.server', trace_id='1c8c9c6d7abc42b4b2b58ef2ae9f9bc5', span_id='87b885f27515d8ae', p...
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/tracing.py", line 718, in finish
    return hub.capture_event(event)
           │   │             └ {'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'sta...
           │   └ <function Hub.capture_event at 0x7f56475b0a40>
           └ <sentry_sdk.hub.Hub object at 0x7f562c23a910>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/hub.py", line 350, in capture_event
    rv = client.capture_event(event, hint, scope)
         │      │             │      │     └ <Scope id=0x7f562daf5180 name=asgi>
         │      │             │      └ None
         │      │             └ {'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'sta...
         │      └ <function _Client.capture_event at 0x7f564761f920>
         └ <sentry_sdk.client._Client object at 0x7f5646a8e210>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/client.py", line 529, in capture_event
    event_opt = self._prepare_event(event, hint, scope)
                │    │              │      │     └ <Scope id=0x7f562daf5180 name=asgi>
                │    │              │      └ {'attachments': []}
                │    │              └ {'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'sta...
                │    └ <function _Client._prepare_event at 0x7f564761f600>
                └ <sentry_sdk.client._Client object at 0x7f5646a8e210>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/client.py", line 291, in _prepare_event
    event_ = scope.apply_to_event(event, hint, self.options)
             │     │              │      │     │    └ {'dsn': 'http://bc41968aa184b886016ce33fba644cc5@10.1.1.90:9000/3', 'max_breadcrumbs': 100, 'release': 'd54efccebbbfc479e5fbf...
             │     │              │      │     └ <sentry_sdk.client._Client object at 0x7f5646a8e210>
             │     │              │      └ {'attachments': []}
             │     │              └ {'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'sta...
             │     └ <function Scope.apply_to_event at 0x7f56479f16c0>
             └ <Scope id=0x7f562daf5180 name=asgi>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/scope.py", line 77, in wrapper
    return fn(self, *args, **kwargs)
           │  │      │       └ {}
           │  │      └ ({'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'st...
           │  └ <Scope id=0x7f562daf5180 name=asgi>
           └ <function Scope.apply_to_event at 0x7f56479f1620>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/scope.py", line 647, in apply_to_event
    new_event = event_processor(event, hint)
                │               │      └ {'attachments': []}
                │               └ {'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'sta...
                └ <function _make_event_processor.<locals>.event_processor at 0x7f562c1eeca0>
> File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/django/__init__.py", line 482, in event_processor
    DjangoRequestExtractor(request).extract_into_event(event)
    │                      │                           └ {'type': 'transaction', 'transaction': '/dashboard/', 'transaction_info': {'source': 'route'}, 'contexts': {'response': {'sta...
    │                      └ <ASGIRequest: GET '/dashboard/'>
    └ <class 'sentry_sdk.integrations.django.DjangoRequestExtractor'>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/_wsgi_common.py", line 73, in extract_into_event
    elif self.raw_data():
         │    └ <function DjangoRequestExtractor.raw_data at 0x7f5646b84e00>
         └ <sentry_sdk.integrations.django.DjangoRequestExtractor object at 0x7f562dc0e250>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/sentry_sdk/integrations/django/__init__.py", line 536, in raw_data
    return self.request.body
           │    │       └ <property object at 0x7f5646ece340>
           │    └ <ASGIRequest: GET '/dashboard/'>
           └ <sentry_sdk.integrations.django.DjangoRequestExtractor object at 0x7f562dc0e250>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/django/http/request.py", line 342, in body
    self._body = self.read()
    │            │    └ <function HttpRequest.read at 0x7f5646e98360>
    │            └ <ASGIRequest: GET '/dashboard/'>
    └ <ASGIRequest: GET '/dashboard/'>
  File "/home/dev-user/.cache/pypoetry/virtualenvs/app-9TtSrW0h-py3.11/lib/python3.11/site-packages/django/http/request.py", line 408, in read
    return self._stream.read(*args, **kwargs)
           │    │       │     │       └ {}
           │    │       │     └ ()
           │    │       └ <function SpooledTemporaryFile.read at 0x7f5648a41300>
           │    └ <tempfile.SpooledTemporaryFile object at 0x7f562dad6530>
           └ <ASGIRequest: GET '/dashboard/'>
  File "/usr/local/lib/python3.11/tempfile.py", line 787, in read
    return self._file.read(*args)
           │    │     │     └ ()
           │    │     └ <method 'read' of '_io.BytesIO' objects>
           │    └ <_io.BytesIO object at 0x7f562ca3fb00>
           └ <tempfile.SpooledTemporaryFile object at 0x7f562dad6530>

ValueError: I/O operation on closed file.
2023-09-15 10:03:50.703 | DEBUG    | logging:callHandlers:1706 - http://10.1.1.90:9000 "POST /api/3/envelope/ HTTP/1.1" 200 0
WebSocket HANDSHAKING /ws/dashboard [172.21.0.11:33942]
2023-09-15 10:03:50.819 | INFO     | logging:callHandlers:1706 - WebSocket HANDSHAKING /ws/dashboard [172.21.0.11:33942]
2023-09-15 10:03:50.819 | DEBUG    | logging:callHandlers:1706 - Upgraded connection ['172.21.0.11', 33942] to WebSocket
WebSocket CONNECT /ws/dashboard [172.21.0.11:33942]
2023-09-15 10:03:50.821 | INFO     | app.dashboard.consumers.dashboard:connect:21 - Accepting websocket request from '172.21.0.11'
2023-09-15 10:03:50.821 | DEBUG    | logging:callHandlers:1706 - WebSocket ['172.21.0.11', 33942] open and established
2023-09-15 10:03:50.821 | INFO     | logging:callHandlers:1706 - WebSocket CONNECT /ws/dashboard [172.21.0.11:33942]
2023-09-15 10:03:50.821 | DEBUG    | logging:callHandlers:1706 - WebSocket ['172.21.0.11', 33942] accepted by application
2023-09-15 10:04:43.504 | DEBUG    | logging:callHandlers:1706 - http://10.1.1.90:9000 "POST /api/3/envelope/ HTTP/1.1" 200 0
```

My sentry configuration:
```python
# Sentry
# ----------------------------------------------------------------------
SENTRY_DSN = get_secret("SENTRY_DSN", try_env=DEBUG)
SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", default=logging.INFO)

sentry_logging = LoggingIntegration(
    level=SENTRY_LOG_LEVEL,  # Capture level info and above as breadcrumbs
    event_level=logging.ERROR,  # Send errors as events
)
integrations = [
    sentry_logging,
    CeleryIntegration(),
    DjangoIntegration(),
    RedisIntegration(),
]
sentry_sdk.init(
    dsn=SENTRY_DSN,
    integrations=integrations,
    environment=env.str("SENTRY_ENVIRONMENT", default="production"),
    traces_sample_rate=env.float("SENTRY_TRACES_SAMPLE_RATE", default=0.0),
    send_default_pii=True,  # To allow collection of X-Forwarded-For
    debug=DEBUG,
)
```

Note that this error is NOT logged by sentry.


Discussion:
Hey @dakotahorstman !
Thanks for reporting this. So you make a requset to `/dashboard` and as I see from the logs you provided (btw, loguru logs are really nice!). So it seams that the Sentry SDK tries to read the ASGI request body and in Django there is a `SpooledTemporaryFile` that has the body but it is somehow closed. 

Could you by any chance come up with a minimal project where I can reproduce this? This would greatly help debugging this.
It will take me a bit of time to create an MRE, but I think I've narrowed it down to something with Daphne/Channels. I just tested with 'runserver_plus', provided by django-extensions, which does not have ASGI support--therefore no channels--and the issue does not occur.

Since my ASGI server in the dev environment is daphne, perhaps something internal in it is causing this (such as prematurely closing the temporary file; not sure). Also, when I access the request body in my views, I can see that it is a bytes string (`types(request.body)` returns `<class 'bytes'>`), and not a spooled temporary file. So, wherever that is being changed is likely the culprit.

I use django-cookiecutter as my project starting point should you want to try and reproduce this while you wait for me to get you an example.
Just tried testing with `daphne -b 0.0.0.0 -p 8000 <application>.asgi:application` and the issue occurs again.
Thanks for the update! As we are a little bit swamped right it will take some time until we can have a look at this.

Resolving patch:
diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py
--- a/sentry_sdk/integrations/django/__init__.py
+++ b/sentry_sdk/integrations/django/__init__.py
@@ -47,6 +47,13 @@
         from django.urls import Resolver404
     except ImportError:
         from django.core.urlresolvers import Resolver404
+
+    # Only available in Django 3.0+
+    try:
+        from django.core.handlers.asgi import ASGIRequest
+    except Exception:
+        ASGIRequest = None
+
 except ImportError:
     raise DidNotEnable("Django not installed")
 
@@ -410,7 +417,7 @@ def _before_get_response(request):
         _set_transaction_name_and_source(scope, integration.transaction_style, request)
 
         scope.add_event_processor(
-            _make_event_processor(weakref.ref(request), integration)
+            _make_wsgi_request_event_processor(weakref.ref(request), integration)
         )
 
 
@@ -462,9 +469,9 @@ def sentry_patched_get_response(self, request):
         patch_get_response_async(BaseHandler, _before_get_response)
 
 
-def _make_event_processor(weak_request, integration):
+def _make_wsgi_request_event_processor(weak_request, integration):
     # type: (Callable[[], WSGIRequest], DjangoIntegration) -> EventProcessor
-    def event_processor(event, hint):
+    def wsgi_request_event_processor(event, hint):
         # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]
         # if the request is gone we are fine not logging the data from
         # it.  This might happen if the processor is pushed away to
@@ -473,6 +480,11 @@ def event_processor(event, hint):
         if request is None:
             return event
 
+        django_3 = ASGIRequest is not None
+        if django_3 and type(request) == ASGIRequest:
+            # We have a `asgi_request_event_processor` for this.
+            return event
+
         try:
             drf_request = request._sentry_drf_request_backref()
             if drf_request is not None:
@@ -489,7 +501,7 @@ def event_processor(event, hint):
 
         return event
 
-    return event_processor
+    return wsgi_request_event_processor
 
 
 def _got_request_exception(request=None, **kwargs):
diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py
--- a/sentry_sdk/integrations/django/asgi.py
+++ b/sentry_sdk/integrations/django/asgi.py
@@ -11,16 +11,56 @@
 from sentry_sdk import Hub, _functools
 from sentry_sdk._types import TYPE_CHECKING
 from sentry_sdk.consts import OP
+from sentry_sdk.hub import _should_send_default_pii
 
 from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
+from sentry_sdk.utils import capture_internal_exceptions
+
+from django.core.handlers.wsgi import WSGIRequest
+
 
 if TYPE_CHECKING:
     from typing import Any
+    from typing import Dict
     from typing import Union
     from typing import Callable
 
+    from django.core.handlers.asgi import ASGIRequest
     from django.http.response import HttpResponse
 
+    from sentry_sdk.integrations.django import DjangoIntegration
+    from sentry_sdk._types import EventProcessor
+
+
+def _make_asgi_request_event_processor(request, integration):
+    # type: (ASGIRequest, DjangoIntegration) -> EventProcessor
+    def asgi_request_event_processor(event, hint):
+        # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]
+        # if the request is gone we are fine not logging the data from
+        # it.  This might happen if the processor is pushed away to
+        # another thread.
+        from sentry_sdk.integrations.django import (
+            DjangoRequestExtractor,
+            _set_user_info,
+        )
+
+        if request is None:
+            return event
+
+        if type(request) == WSGIRequest:
+            return event
+
+        with capture_internal_exceptions():
+            DjangoRequestExtractor(request).extract_into_event(event)
+
+        if _should_send_default_pii():
+            with capture_internal_exceptions():
+                _set_user_info(request, event)
+
+        return event
+
+    return asgi_request_event_processor
+
 
 def patch_django_asgi_handler_impl(cls):
     # type: (Any) -> None
@@ -31,16 +71,46 @@ def patch_django_asgi_handler_impl(cls):
 
     async def sentry_patched_asgi_handler(self, scope, receive, send):
         # type: (Any, Any, Any, Any) -> Any
-        if Hub.current.get_integration(DjangoIntegration) is None:
+        hub = Hub.current
+        integration = hub.get_integration(DjangoIntegration)
+        if integration is None:
             return await old_app(self, scope, receive, send)
 
         middleware = SentryAsgiMiddleware(
             old_app.__get__(self, cls), unsafe_context_data=True
         )._run_asgi3
+
         return await middleware(scope, receive, send)
 
     cls.__call__ = sentry_patched_asgi_handler
 
+    modern_django_asgi_support = hasattr(cls, "create_request")
+    if modern_django_asgi_support:
+        old_create_request = cls.create_request
+
+        def sentry_patched_create_request(self, *args, **kwargs):
+            # type: (Any, *Any, **Any) -> Any
+            hub = Hub.current
+            integration = hub.get_integration(DjangoIntegration)
+            if integration is None:
+                return old_create_request(self, *args, **kwargs)
+
+            with hub.configure_scope() as scope:
+                request, error_response = old_create_request(self, *args, **kwargs)
+
+                # read the body once, to signal Django to cache the body stream
+                # so we can read the body in our event processor
+                # (otherwise Django closes the body stream and makes it impossible to read it again)
+                _ = request.body
+
+                scope.add_event_processor(
+                    _make_asgi_request_event_processor(request, integration)
+                )
+
+                return request, error_response
+
+        cls.create_request = sentry_patched_create_request
+
 
 def patch_get_response_async(cls, _before_get_response):
     # type: (Any, Any) -> None


Test patch:
diff --git a/tests/integrations/django/asgi/test_asgi.py b/tests/integrations/django/asgi/test_asgi.py
--- a/tests/integrations/django/asgi/test_asgi.py
+++ b/tests/integrations/django/asgi/test_asgi.py
@@ -7,6 +7,11 @@
 from sentry_sdk.integrations.django import DjangoIntegration
 from tests.integrations.django.myapp.asgi import channels_application
 
+try:
+    from django.urls import reverse
+except ImportError:
+    from django.core.urlresolvers import reverse
+
 try:
     from unittest import mock  # python 3.3 and above
 except ImportError:
@@ -353,3 +358,47 @@ async def test_trace_from_headers_if_performance_disabled(sentry_init, capture_e
 
     assert msg_event["contexts"]["trace"]["trace_id"] == trace_id
     assert error_event["contexts"]["trace"]["trace_id"] == trace_id
+
+
+@pytest.mark.parametrize("application", APPS)
+@pytest.mark.parametrize(
+    "body,expected_return_data",
+    [
+        (
+            b'{"username":"xyz","password":"xyz"}',
+            {"username": "xyz", "password": "xyz"},
+        ),
+        (b"hello", ""),
+        (b"", None),
+    ],
+)
+@pytest.mark.asyncio
+@pytest.mark.skipif(
+    django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1"
+)
+async def test_asgi_request_body(
+    sentry_init, capture_envelopes, application, body, expected_return_data
+):
+    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
+
+    envelopes = capture_envelopes()
+
+    comm = HttpCommunicator(
+        application,
+        method="POST",
+        path=reverse("post_echo_async"),
+        body=body,
+        headers=[(b"content-type", b"application/json")],
+    )
+    response = await comm.get_response()
+
+    assert response["status"] == 200
+    assert response["body"] == body
+
+    (envelope,) = envelopes
+    event = envelope.get_event()
+
+    if expected_return_data is not None:
+        assert event["request"]["data"] == expected_return_data
+    else:
+        assert "data" not in event["request"]
diff --git a/tests/integrations/django/myapp/urls.py b/tests/integrations/django/myapp/urls.py
--- a/tests/integrations/django/myapp/urls.py
+++ b/tests/integrations/django/myapp/urls.py
@@ -82,6 +82,11 @@ def path(path, *args, **kwargs):
         path("async/thread_ids", views.thread_ids_async, name="thread_ids_async")
     )
 
+if views.post_echo_async is not None:
+    urlpatterns.append(
+        path("post_echo_async", views.post_echo_async, name="post_echo_async")
+    )
+
 # rest framework
 try:
     urlpatterns.append(
diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py
--- a/tests/integrations/django/myapp/views.py
+++ b/tests/integrations/django/myapp/views.py
@@ -235,7 +235,15 @@ def thread_ids_sync(*args, **kwargs):
     })
     return HttpResponse(response)"""
     )
+
+    exec(
+        """@csrf_exempt
+def post_echo_async(request):
+    sentry_sdk.capture_message("hi")
+    return HttpResponse(request.body)"""
+    )
 else:
     async_message = None
     my_async_view = None
     thread_ids_async = None
+    post_echo_async = None