Duplicate exception handler definition on: route=__ALL_ROUTES__ and exception=<class 'sanic_jwt.exceptions.SanicJWTException'>
from sanic import Sanic, Blueprint
from sanic_jwt import Initialize
app = Sanic("TestCase")
bp = Blueprint('bp', url_prefix='/api')
app.blueprint(bp)
bp1 = Blueprint('bp1', url_prefix='/test')
app.blueprint(bp1)
Initialize(
instance=bp,
app=app,
authenticate=lambda: True
)
Initialize(
instance=bp1,
app=app,
authenticate=lambda: True
)
print('app', app.router.routes_all.keys())
print('bp', [x.uri for x in bp.routes])
This code gives me following Error. Looks like bug, i don't understand why.
Traceback (most recent call last):
File "/home/deffuls/Documents/Example/test.py", line 20, in <module>
Initialize(
File "/home/deffuls/Documents/Example/env_py/lib/python3.11/site-packages/sanic_jwt/initialization.py", line 137, in __init__
self.__add_endpoints()
File "/home/deffuls/Documents/Example/env_py/lib/python3.11/site-packages/sanic_jwt/initialization.py", line 179, in __add_endpoints
self.app.exception(exceptions.SanicJWTException)(
File "/home/deffuls/Documents/Example/env_py/lib/python3.11/site-packages/sanic/mixins/exceptions.py", line 37, in decorator
self._apply_exception_handler(future_exception)
File "/home/deffuls/Documents/Example/env_py/lib/python3.11/site-packages/sanic/app.py", line 517, in _apply_exception_handler
self.error_handler.add(exception, handler.handler, route_names)
File "/home/deffuls/Documents/Example/env_py/lib/python3.11/site-packages/sanic/handlers/error.py", line 73, in add
self._add((exception, None), handler)
File "/home/deffuls/Documents/Exampleenv_py/lib/python3.11/site-packages/sanic/handlers/error.py", line 53, in _add
raise ServerError(message)
sanic.exceptions.ServerError: Duplicate exception handler definition on: route=__ALL_ROUTES__ and exception=<class 'sanic_jwt.exceptions.SanicJWTException'>
I also encountered a Duplicate exception hander definition on: ... exception recently. In my case, I had defined an error handler that attempts to handle the same error twice.
The code that caused the error was this:
from sanic import Sanic
from sanic import Request
from sanic.response import JSONResponse
from sanic.exceptions import BadRequest
from sanic.exceptions import InvalidUsage
from sanic.exceptions import HTTPException
app = Sanic(app_name, strict_slashes=False)
@app.exception(BadRequest, InvalidUsage)
async def handle_authentication_error(request: Request, exception: HTTPException) -> JSONResponse:
logger.exception(exception)
return response.json(
{
"description": "<some_description>",
"status": exception.status_code,
"reason": exception.message
},
status=exception.status_code
)
# rest of the code ...
here BadRequest, and InvalidUsage both points to the same exception definition BadRequest. Got it fixed by removing InvalidUsage, leaving only a single exception handler for a specific exception def.
However, I don't see any custom exception handling done in your code so not really sure what's the issue here.
when you call
Initialize(
instance=bp,
app=app,
authenticate=lambda: True
)
Initialize(
instance=bp1,
app=app,
authenticate=lambda: True
)
Each JWT instance registers a new global handler for SanicJWTException on the same app object. But Sanic’s core rule is:
You can only register one handler per (exception, route) pair.
So the second registration triggers:
ServerError: Duplicate exception handler definition on: route=__ALL_ROUTES__ and exception=<class 'sanic_jwt.exceptions.SanicJWTException'>
I tried to remove duplicated handler by overwriting Initialize function:
class SafeJWTInitialize(Initialize):
@staticmethod
def remove_jwt_exception_handler(app):
"""
Remove existing SanicJWTException handler for the current Sanic app.
Works for versions where ErrorHandler uses `cached_handlers`.
"""
key = (SanicJWTException, None)
handlers_dict = getattr(app.error_handler, "cached_handlers", {})
if key in handlers_dict:
del handlers_dict[key]
"""Initialize JWT safely without duplicate exception handler errors."""
def __init__(self, instance, app=None, **kwargs):
if app:
self.remove_jwt_exception_handler(app)
super().__init__(instance=instance, app=app, **kwargs)
Then, instead of call
Initialize(
instance=bp,
app=app,
authenticate=lambda: True
)
just do
SafeJWTInitialize(
instance=bp,
app=app,
authenticate=lambda: True
)
That automatically removes the duplicate handler each time
It's a bit hacky but should solve the problem.