Opened 21 months ago

Last modified 16 months ago

#34451 assigned Bug

Incorrect exception handling within the django exception handler

Reported by: Michael Galler Owned by: Akshat verma
Component: Error reporting Version: 4.1
Severity: Normal Keywords:
Cc: asgi Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Mariusz Felisiak)

start with

django-admin startproject myproject

views.py

from django.views.generic import FormView


class TestView(FormView):

    async def post(self, request, *args, **kwargs):
        return 'Foobar'

urls.py

from django.contrib import admin
from django.urls import path

from myproject.views import TestView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/', TestView.as_view()),
]

This should raise
django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.

Running the devserver via manage.py results in

C:\code\myproject\venv\Scripts\python.exe C:\code\myproject\manage.py runserver 8000 
Performing system checks...

Watching for file changes with StatReloader
Exception in thread django-main-thread:
Traceback (most recent call last):
  File "C:\Program Files\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "C:\Program Files\Python311\Lib\threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "C:\code\myproject\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 134, in inner_run
    self.check(display_num_errors=True)
  File "C:\code\myproject\venv\Lib\site-packages\django\core\management\base.py", line 475, in check
    all_issues = checks.run_checks(
                 ^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config
    return check_resolver(resolver)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver
    return check_method()
           ^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 494, in check
    for pattern in self.url_patterns:
                   ^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
                       ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module
    return import_module(self.urlconf_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\code\myproject\myproject\urls.py", line 8, in <module>
    path('test/', TestView.as_view()),
                  ^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view
    if cls.view_is_async:
       ^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__
    return self.fget(cls)
           ^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.

Now the same thing with hypercorn will result in some sort of recursion that I do not understand.
Uvicorn behaves the same way.

(venv) λ hypercorn myproject.asgi:application
[2023-03-31 11:54:00 +0200] [16000] [WARNING] ASGI Framework Lifespan error, continuing without Lifespan support
[2023-03-31 11:54:00 +0200] [16000] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit)
[2023-03-31 11:54:08 +0200] [16000] [ERROR] Error in ASGI Framework
Traceback (most recent call last):
  File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 486, in thread_handler
    raise exc_info[1]
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 43, in inner
    response = await get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 235, in _get_response_async
    callback, callback_args, callback_kwargs = self.resolve_request(request)
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 313, in resolve_request
    resolver_match = resolver.resolve(request.path_info)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 663, in resolve
    for pattern in self.url_patterns:
                   ^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
                       ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module
    return import_module(self.urlconf_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\code\myproject\myproject\urls.py", line 8, in <module>
    path('test/', TestView.as_view()),
                  ^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view
    if cls.view_is_async:
       ^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__
    return self.fget(cls)
           ^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.

During handling of the above exception, another exception occurred:

... (the same frame over and over again)

In my personal project this leads to a strange problem with django-ninja

api.py

from ninja import NinjaAPI

api = NinjaAPI()

urls.py

from django.contrib import admin
from django.urls import path

from myproject.api import api
from myproject.views import TestView

urlpatterns = [
    path('admin/', admin.site.urls),
    path("api/", api.urls),
    path('test/', TestView.as_view()),
]

manage.py devserver:

C:\code\myproject\venv\Scripts\python.exe C:\code\myproject\manage.py runserver 8000 
Watching for file changes with StatReloader
Performing system checks...

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "C:\Program Files\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "C:\Program Files\Python311\Lib\threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "C:\code\myproject\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 134, in inner_run
    self.check(display_num_errors=True)
  File "C:\code\myproject\venv\Lib\site-packages\django\core\management\base.py", line 475, in check
    all_issues = checks.run_checks(
                 ^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config
    return check_resolver(resolver)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver
    return check_method()
           ^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 494, in check
    for pattern in self.url_patterns:
                   ^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
                       ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module
    return import_module(self.urlconf_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\code\myproject\myproject\urls.py", line 10, in <module>
    path('test/', TestView.as_view()),
                  ^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view
    if cls.view_is_async:
       ^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__
    return self.fget(cls)
           ^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.

With hypercorn:

(venv) λ hypercorn myproject.asgi:application                                                                                                            
[2023-03-31 12:03:33 +0200] [20028] [WARNING] ASGI Framework Lifespan error, continuing without Lifespan support                                         
[2023-03-31 12:03:33 +0200] [20028] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit)                                                           
[2023-03-31 12:03:40 +0200] [20028] [ERROR] Error in ASGI Framework                                                                                      
Traceback (most recent call last):                                                                                                                       
  File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 486, in thread_handler                                                           
    raise exc_info[1]                                                                                                                                    
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 43, in inner                                                   
    response = await get_response(request)                                                                                                               
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                               
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 235, in _get_response_async                                         
    callback, callback_args, callback_kwargs = self.resolve_request(request)                                                                             
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                             
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 313, in resolve_request                                             
    resolver_match = resolver.resolve(request.path_info)                                                                                                 
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                 
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 663, in resolve                                                         
    for pattern in self.url_patterns:                                                                                                                    
                   ^^^^^^^^^^^^^^^^^                                                                                                                     
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__                                                        
    res = instance.__dict__[self.name] = self.func(instance)                                                                                             
                                         ^^^^^^^^^^^^^^^^^^^                                                                                             
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns                                                    
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)                                                                          
                       ^^^^^^^^^^^^^^^^^^^                                                                                                               
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__                                                        
    res = instance.__dict__[self.name] = self.func(instance)                                                                                             
                                         ^^^^^^^^^^^^^^^^^^^                                                                                             
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module                                                  
    return import_module(self.urlconf_name)                                                                                                              
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                              
  File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module                                                                
    return _bootstrap._gcd_import(name[level:], package, level)                                                                                          
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                          
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import                                                                                        
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load                                                                                     
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked                                                                            
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked                                                                                      
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module                                                                                
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed                                                                           
  File "C:\code\myproject\myproject\urls.py", line 10, in <module>                                                                                       
    path('test/', TestView.as_view()),                                                                                                                   
                  ^^^^^^^^^^^^^^^^^^                                                                                                                     
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view                                                     
    if cls.view_is_async:                                                                                                                                
       ^^^^^^^^^^^^^^^^^                                                                                                                                 
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__                                                        
    return self.fget(cls)                                                                                                                                
           ^^^^^^^^^^^^^^                                                                                                                                
  File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async                                                
    raise ImproperlyConfigured(                                                                                                                          
django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.                                                
                                                                                                                                                         
During handling of the above exception, another exception occurred:                                                                                      
                                                                                                                                                         
Traceback (most recent call last):                                                                                                                       
  File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 486, in thread_handler                                                           
    raise exc_info[1]                                                                                                                                    
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 43, in inner                                                   
    response = await get_response(request)                                                                                                               
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                               
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\deprecation.py", line 152, in __acall__                                                    
    response = response or await self.get_response(request)                                                                                              
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                              
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 45, in inner                                                   
    response = await sync_to_async(                                                                                                                      
               ^^^^^^^^^^^^^^^^^^^^                                                                                                                      
  File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 448, in __call__                                                                 
    ret = await asyncio.wait_for(future, timeout=None)                                                                                                   
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                   
  File "C:\Program Files\Python311\Lib\asyncio\tasks.py", line 442, in wait_for                                                                          
    return await fut                                                                                                                                     
           ^^^^^^^^^                                                                                                                                     
  File "C:\Program Files\Python311\Lib\concurrent\futures\thread.py", line 58, in run                                                                    
    result = self.fn(*self.args, **self.kwargs)                                                                                                          
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                          
  File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 488, in thread_handler                                                           
    return func(*args, **kwargs)                                                                                                                         
           ^^^^^^^^^^^^^^^^^^^^^                                                                                                                         
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 141, in response_for_exception                                 
    response = handle_uncaught_exception(                                                                                                                
               ^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 182, in handle_uncaught_exception                              
    return debug.technical_500_response(request, *exc_info)                                                                                              
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                              
  File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 66, in technical_500_response                                              
    html = reporter.get_traceback_html()                                                                                                                 
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                 
  File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 396, in get_traceback_html                                                 
    c = Context(self.get_traceback_data(), use_l10n=False)                                                                                               
                ^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                
  File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 381, in get_traceback_data                                                 
    c["raising_view_name"] = get_caller(self.request)                                                                                                    
                             ^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                    
  File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 99, in get_caller                                                          
    resolver_match = resolve(request.path)                                                                                                               
                     ^^^^^^^^^^^^^^^^^^^^^                                                                                                               
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\base.py", line 24, in resolve                                                               
    return get_resolver(urlconf).resolve(path)                                                                                                           
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                           
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 663, in resolve                                                         
    for pattern in self.url_patterns:                                                                                                                    
                   ^^^^^^^^^^^^^^^^^                                                                                                                     
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__                                                        
    res = instance.__dict__[self.name] = self.func(instance)                                                                                             
                                         ^^^^^^^^^^^^^^^^^^^                                                                                             
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns                                                    
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)                                                                          
                       ^^^^^^^^^^^^^^^^^^^                                                                                                               
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__                                                        
    res = instance.__dict__[self.name] = self.func(instance)                                                                                             
                                         ^^^^^^^^^^^^^^^^^^^                                                                                             
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module                                                  
    return import_module(self.urlconf_name)                                                                                                              
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                              
  File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module                                                                
    return _bootstrap._gcd_import(name[level:], package, level)                                                                                          
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                          
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import                                                                                        
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load                                                                                     
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked                                                                            
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked                                                                                      
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module                                                                                
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed                                                                           
  File "C:\code\myproject\myproject\urls.py", line 9, in <module>                                                                                        
    path("api/", api.urls),                                                                                                                              
                 ^^^^^^^^                                                                                                                                
  File "C:\code\myproject\venv\Lib\site-packages\ninja\main.py", line 379, in urls                                                                       
    self._validate()                                                                                                                                     
  File "C:\code\myproject\venv\Lib\site-packages\ninja\main.py", line 494, in _validate                                                                  
    raise ConfigError(msg.strip())                                                                                                                       
ninja.errors.ConfigError: Looks like you created multiple NinjaAPIs or TestClients                                                                       
To let ninja distinguish them you need to set either unique version or urls_namespace                                                                    
 - NinjaAPI(..., version='2.0.0')                                                                                                                        
 - NinjaAPI(..., urls_namespace='otherapi')                                                                                                              
Already registered: ['api-1.0.0']                                                                                                                        
                                                                                                                                                         
During handling of the above exception, another exception occurred:

... (the same frame over and over again)                                                                                                                   

Change History (7)

comment:1 by Mariusz Felisiak, 21 months ago

Description: modified (diff)

comment:2 by Mariusz Felisiak, 21 months ago

Description: modified (diff)

comment:3 by Mariusz Felisiak, 21 months ago

Cc: asgi added
Component: UncategorizedCore (Other)
Resolution: invalid
Status: newclosed

Hi, thanks for the report, however, I don't think you've explained the issue in enough detail to confirm a bug in Django. It works fine with Django built-in runserver and with daphne's runserver (see docs). The repeated frame (5-6 times) in a non-development web servers doesn't look like an issue in Django itself.

TBH, I think it's an issue in web servers. For example, it works properly when I change ImproperlyConfigured class to inherit from BaseException instead of Exception, but that should not be the case as BaseException is not intended to be directly inherited from user-defined exceptions.

IMO, you should try to report it in web server bug trackers or in Python itself (check for duplicated first).

comment:4 by Michael Galler, 21 months ago

Resolution: invalid
Status: closednew
Summary: Incorrect handling of ImproperlyConfigured Exception in views in ASGI contextIncorrect exception handling within the django exception handler

After some digging I am sure that this is a django problem.
The problem also occurs in wsgi mode, tested with waitress.
The devserver already does several checks before it starts which are not done by asgi/wsgi handlers.
These checks already detect the problem and prevent the start of the http server.

if i disable the checks in the following file

venv/Lib/site-packages/django/core/management/base.py

    def check(
        self,
        app_configs=None,
        tags=None,
        display_num_errors=False,
        include_deployment_checks=False,
        fail_level=checks.ERROR,
        databases=None,
    ):
        """
        Use the system check framework to validate entire Django project.
        Raise CommandError for any serious message (error or critical errors).
        If there are only light messages (like warnings), print them to stderr
        and don't raise an exception.
        """
        return



Now the devserver behaves the same way

 File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 141, in get_response
    response = self._middleware_chain(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 58, in inner
    response = response_for_exception(request, exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 141, in response_for_exception
    response = handle_uncaught_exception(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 185, in handle_uncaught_exception
    callback = resolver.resolve_error_handler(500)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 729, in resolve_error_handler
    callback = getattr(self.urlconf_module, "handler%s" % view_type, None)
                       ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module
    return import_module(self.urlconf_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\code\myproject\myproject\urls.py", line 10, in <module>
    path('test/', TestView.as_view()),

If I interpret this correctly, the problem is that the exception handler tries to render the 500 page, which imports the urls which leads to the same error.
The exception handler seems to have problems when it causes exceptions itself :D

in reply to:  4 comment:6 by Mariusz Felisiak, 21 months ago

Component: Core (Other)Error reporting
Triage Stage: UnreviewedAccepted

If I interpret this correctly, the problem is that the exception handler tries to render the 500 page, which imports the urls which leads to the same error.

Tentatively accepted for future investigation. It seems that at least resolve_error_handler()/get_caller() should handle errors when checking the URLconf/resolving paths.

comment:7 by Akshat verma, 21 months ago

Owner: changed from nobody to Akshat verma
Status: newassigned

comment:8 by Enrique Matías Sánchez, 16 months ago

Note: See TracTickets for help on using tickets.
Back to Top