-
Notifications
You must be signed in to change notification settings - Fork 99
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
Issue running starlette: TypeError: _run_asgi2() takes 2 positional arguments but 4 were given #117
Comments
Interesting @cancan101 , thanks for filing an issue! From that stack trace, it looks like what's happening is the starlette errors middleware (using ASGI v3 protocol) is calling an ASGI v2 application, which is incompatible, causing the crash.
|
yes
I don't have that any where in my project code
I think this is being caused by the Sentry asgi middleware: https://github.com/getsentry/sentry-python/blob/dbd7ce89b24df83380900895307642138a74d27a/sentry_sdk/integrations/asgi.py#L91-L94 |
That definitely does seem to be the cause! How did you add the sentry middleware? This is the app I'm running with and I can't reproduce the crash: from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.responses import PlainTextResponse
from starlette.routing import Route
async def pong(request):
return PlainTextResponse("*")
routes = [
Route("/", pong),
]
app = Starlette(routes=routes, middleware=[Middleware(SentryAsgiMiddleware)]) |
I am also using this middleware which seems to be causing the issue: https://github.com/mfreeborn/fastapi-sqlalchemy/blob/39e7e8bb5d98a9de5fc365adf4bdc661d824b614/fastapi_sqlalchemy/middleware.py#L18-L45 |
It seems like |
Ok the issue doesn't seem to be specific to the DB middleware, it is just having any other middleware after the sentry middleware that triggers the issue. |
If there is no other middleware specified then the next middleware after sentry is newrelic-python-agent/newrelic/hooks/framework_starlette.py Lines 219 to 226 in ca22180
|
Thanks for that info, I've reproduced the issue and I'm investigating. from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.routing import Route
async def pong(request):
return PlainTextResponse("*")
routes = [
Route("/", pong),
]
app = Starlette(routes=routes)
@app.middleware("http")
async def middleware_with_decorator(request, call_next):
response = await call_next(request)
return response
app.add_middleware(SentryAsgiMiddleware) |
We've encountered this kind of problem before because ASGI2/3 detection via attribute introspection doesn't work very well with wrapt function wrappers. We had to fix this in uvicorn by deferring the assignment of the wrapper until the interface modes were resolved. We're just discussing now how to address these kinds of issues. |
Maybe @GrahamDumpleton has ideas on how to solve this issue? 😄 There may be some things that can be done in wrapt, such as inspecting if the wrapper function is a coroutine function and then propagating attributes / flags upward. |
The TL/DR as I understand it currently: import asyncio
def foo():
return bar()
async def bar():
return await asyncio.sleep(0)
# >>> False
print("asyncio.iscoroutinefunction(foo)", asyncio.iscoroutinefunction(foo))
# >>> True
print("asyncio.iscoroutine(foo())", asyncio.iscoroutine(foo())) |
Neither the wrapt The This is why the base The only possible solution have thought might be able to use to resolve the problem is to have the constructor for the proxy object perform a check whether a normal function, async function is passed and add extra proxy functions to the wrapper instance in that case for async. Complicating this though is that you also have async generators and async context managers, so you need to look for the presence of each specific possible async dunder method and create a proxy function for each one as found. This will create a bit of overhead on construction and overhead may mount up over time if done on the generic project. For So suggest adding to the newrelic FunctionWrapper equivalent a constructor which checks for Anyway, since not really been devoting any time to improving wrapt, I have been ignoring the whole async issues for a very long time now. So this isn't the only related issue.
Ability to put time in on this is a bit complicated right now. |
Thanks for the note @GrahamDumpleton ❤️ ! These are some really good ideas, we'll discuss on the team to decide which way we'll resolve this. We'll also discuss/explore if we can contribute back to wrapt, keeping in mind any limited time you have for review 🚀 . |
@cancan101 While we investigate, you should be able to work around this issue by forcing all requests to be treated as ASGI v3 by adding this patch: SentryAsgiMiddleware._run_asgi2 = SentryAsgiMiddleware._run_asgi3 This forces the Example app: from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.routing import Route
async def pong(request):
return PlainTextResponse("*")
routes = [
Route("/", pong),
]
app = Starlette(routes=routes)
@app.middleware("http")
async def middleware_with_decorator(request, call_next):
response = await call_next(request)
return response
SentryAsgiMiddleware._run_asgi2 = SentryAsgiMiddleware._run_asgi3
app.add_middleware(SentryAsgiMiddleware) |
I wonder if this was a similar issue that Starlette ran into and if so if there is any inspiration to be taken from their solution:? encode/starlette#1106 |
The problem is that the sentry middleware is classifying our wrapper (an ASGI v3 app) as an ASGI v2 app. Therefore, any fix around detection logic would have to be applied to the sentry middleware itself. It might be worth putting in a feature request with Sentry to specify the ASGI type via the constructor rather than relying on auto detection in all cases. uvicorn provides a switch to set the ASGI interface (via the |
What exactly is the supposed difference between ASGI 2 and 3 calling interface. As far as I can tell, wrapt actually seems to be giving the correct results.
This yields:
So the results are same when the decorator is applied. Anyone have an example of ASGI 2 code so can check with it? Right now looks like issue may be elsewhere. |
This was the reproduction case I used if you wanted to have a look @GrahamDumpleton 😄 The repro needs to be run with |
Should add one comment. The reason that wrapt gives the correct results is that |
For full transparency, it's totally possible that I completely mis-classified the problem, in which case I'm sure Graham will take me to school here 😅 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This is still an issue for us with similar circumstances. |
This is still an issue for us too, while we are using ASGI middleware for sentry and New Relic as monitoring service. |
Is this truly a wontfix? We are currently running into this with one of our FastAPI projects, and don't want to have to make a choice between NewRelic and Sentry. |
Why has this been marked as wontfix? We are having the same issue and even trying the alternative method (here: https://docs.newrelic.com/docs/apm/agents/python-agent/installation/python-agent-advanced-integration/#manual-integration ) we have exactly the same error. Basically we have no way to use New Relic in our application because we are also using Sentry. |
I think sentry-python v1.8.0 release fixes this! |
still an open issue. don't want to drop newrelic. |
We have the same issue |
We're facing this too, trying to evaluate New Relic and Datadog at the moment. |
We have a PR (linked to this issue) up now to patch this that should go out in our next release. The branch is available for earlier testing as well. |
Hello all, the PR has been merged. Closing this issue unless someone reports they are still experiencing it. Here is the latest version which includes the fix: Python 8.5.0 |
I am getting the following traceback when trying to launch an asgi server with starlette:
I am using this run command:
newrelic-admin run-program gunicorn -w 4 -k uvicorn.workers.UvicornWorker my_package:app
Using:
The text was updated successfully, but these errors were encountered: