cors and error status 500 and handle it in frontend #7847
Replies: 20 comments 5 replies
-
|
I also have this question. I have confusion with a developer who thinks there is a CORS issue when receiving any 500 error response, though the As a workaround, I noticed that if I manually do: Then the CORS headers are included in the 500 response. I apologize if this is just my ignorance of best practices. I expected default 500 responses returned from uncaught Python exceptions to include the CORS headers given in |
Beta Was this translation helpful? Give feedback.
-
|
If you receive a 500 response that means you have an error in your backend app code (Python using FastAPI). It doesn't have anything to do with CORS. If you have an error, your app won't be able to send any headers used for CORS. But the problem is not at CORS, is before that. Check your error logs, from your Python code, where you run Uvicorn. |
Beta Was this translation helpful? Give feedback.
-
|
Thank you, @tiangolo. I've found those app code errors. Right now I keep all my endpoints wrapped in a general try/except and manually return 500 responses to preserve the CORS headers for such cases. Is there a better way to have the CORS headers included for future app errors I haven't identified? |
Beta Was this translation helpful? Give feedback.
-
|
@statueofmike I had the same issue recently, you don't need to wrap each endpoint with try/catch manually, you can do that once in the custom exception-catching middleware. Assuming that browser sends request from localhost:3000 to api on port 8080, |
Beta Was this translation helpful? Give feedback.
-
|
Ran into this myself as well. Almost didn't think that adding a handler for
|
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the discussion and ideas here! On the other side, let me suggest you all to try sentry.io It has a free tier, and it might change your life 😉 In some cases, it can detect and show errors even better than what you could while debugging locally. And for 500 errors that you want to be sure you know what's having errors, even during production, that could be a vital tool. |
Beta Was this translation helpful? Give feedback.
-
|
@statueofmike @rigward Thanks for your reply. The idea is to handle the unforeseen error to avoid missing cors header. @tiangolo Thanks for your suggestion. |
Beta Was this translation helpful? Give feedback.
-
|
For anyone who comes across this in the future in search of a solution, below is how we've decided to handle this using a custom 500 exception handler. @app.exception_handler(500)
async def custom_http_exception_handler(request, exc):
error = ErrorResponse(error="Something went wrong")
error = jsonable_encoder(error.dict())
response = JSONResponse(content=error, status_code=500)
# Since the CORSMiddleware is not executed when an unhandled server exception
# occurs, we need to manually set the CORS headers ourselves if we want the FE
# to receive a proper JSON 500, opposed to a CORS error.
# Setting CORS headers on server errors is a bit of a philosophical topic of
# discussion in many frameworks, and it is currently not handled in FastAPI.
# See dotnet core for a recent discussion, where ultimately it was
# decided to return CORS headers on server failures:
# https://github.com/dotnet/aspnetcore/issues/2378
origin = request.headers.get('origin')
if origin:
# Have the middleware do the heavy lifting for us to parse
# all the config, then update our response headers
cors = CORSMiddleware(
app=app,
allow_origins=ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"])
# Logic directly from Starlette's CORSMiddleware:
# https://github.com/encode/starlette/blob/master/starlette/middleware/cors.py#L152
response.headers.update(cors.simple_headers)
has_cookie = "cookie" in request.headers
# If request includes any cookie headers, then we must respond
# with the specific origin instead of '*'.
if cors.allow_all_origins and has_cookie:
response.headers["Access-Control-Allow-Origin"] = origin
# If we only allow specific origins, then we have to mirror back
# the Origin header in the response.
elif not cors.allow_all_origins and cors.is_allowed_origin(origin=origin):
response.headers["Access-Control-Allow-Origin"] = origin
response.headers.add_vary_header("Origin")
return response |
Beta Was this translation helpful? Give feedback.
-
|
I solved it like this, however it works only if specific exception is given to app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=ALLOWED_ORIGINS,
allow_methods=["*"],
allow_headers=["*"],
)
@app.exception_handler(SpecificException)
async def specific_exception_handler(request, exc):
return JSONResponse(status_code=500, content={"body": "Internal Server Error"})more info: https://fastapi.tiangolo.com/tutorial/handling-errors/#install-custom-exception-handlers what @rigward proposed in #775 (comment) works BUT is not an optimal solution IMO |
Beta Was this translation helpful? Give feedback.
-
@tiangolo sentry is a good suggestions and should be implemented by the masses, but the problem i think comes with how this error is reported to the user. What's happening is the route faults and the caller is receiving a browser message saying 'CORS header 'Access-Control-Allow-Origin' missing' obscuring the actual error. This causes a wild goose chase in CORS settings on servers and client for some amount of time before someone realizes they should check the server logs for the actual error, even if they're using sentry. After the realization is CORS headers aren't sent during default exception handling we Google and stumble on this thread followed by a copy/paste of someone's work around. I think this issue is one of friction/confusion which isn't solved by improving log ingestion. If CORS is misconfigured then a CORS error should be displayed, but if CORS is configured correctly then the CORS error should not appear, and the 500 error would now suggest to the user "check the server logs". This is, in my experience, how other frameworks function. |
Beta Was this translation helpful? Give feedback.
-
|
This issue should be reopened. CORSMiddleware should also apply to the exception handlers. No workaround should be needed. |
Beta Was this translation helpful? Give feedback.
-
|
I'd disagree, this is not a FastAPI issue but a Starlette implementation consequence. I would recommend to have the discussion over there. See also this issue Kludex/starlette#1175 |
Beta Was this translation helpful? Give feedback.
-
|
Seems reasonable, then the issue at Starlette should be reopened. |
Beta Was this translation helpful? Give feedback.
-
|
I like #775 (comment) workaround, but don't get, how to tie that with another workaround, described here: #1216 (comment). In which order are exception handlers, middleware and routers are executed, can someone point me? |
Beta Was this translation helpful? Give feedback.
-
Hi @jkamdjou, I tried to use your code, and unfortunately looks like status_code as a parameter does not work, or maybe I miss something, could you please elaborate on where this code should be placed? |
Beta Was this translation helpful? Give feedback.
-
|
Not providing CORS-related headers in the case of an error is a real antipattern to modern web communication, where CORS is treated as essential and non-negotiable by all common browsers. I don't think this should be delegated to framework users. Please reopen. |
Beta Was this translation helpful? Give feedback.
-
|
Hello, just adding to the discussion. Another problem with this is that (at least in an SPA where you make a request with axios) it is impossible to differentiate a request with an internal server error from a request where the server is offline. This is relevant for production as well I guess? |
Beta Was this translation helpful? Give feedback.
-
|
Just chiming in here, this is also a weird problem that I've stumbled into. Spent a very long time trying to understand the intricacies of why this 500 error was generating a CORS failure and finally ran into this topic. Definitely a unique pattern, perhaps needs more documentation if it remains open. (Per always, I write with constructive critiques, fastapi is excellent work.) |
Beta Was this translation helpful? Give feedback.
-
|
Adding my voice to the choir... I find this behavior confusing, it's not what I would expect. |
Beta Was this translation helpful? Give feedback.
-
|
I think we can close this topic. The discussion #8027 addresses the reported issue. |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
First check
Description
When there is 500 error happens, the response header contains no information about cors. The browser console says: 'Reason: CORS header 'Access-Control-Allow-Origin' missing'
I want to check the status code in in frontend(vue) with axios and alert a error message, but there is no error.response.status in axios catch. I guess it is related to the cors bedore the browser complains it in console.
Code to generate error 500
Below is the response header of 500. There is no cors info.
Is it intended to behave like this? Or it may be a bug?
EDIT:
I finally get the 500 error handled in frontend after read the axios doc. I keep it open because I'm still curious about it.
Beta Was this translation helpful? Give feedback.
All reactions