RuntimeError: populate() isn't reentrant

My company has a complex Django-based app that is redeployed across different environments with different modules activated. I occasionally run into this error:

RuntimeError: populate() isn’t reentrant

But this is not a useful error. Following this instruction (from stackoverflow):

open django/apps/registry.py and around line 80, replace:
raise RuntimeError(“populate() isn’t reentrant”)
with:
self.app_configs = {}

reveals a better error, which is often a bad import. However it requires editing the Django installed package from within python site-packages. Can we just replace that exception, or if it serves a purpose under some error conditions, let some setting allow a path to skip that exception? It is impossible to debug the true error in our large code base when all we get is that error.

Thanks.

Are you only getting this error message, or are you getting the traceback as well?

If you’re only getting the error message, then you could add code into that section of registry.py to print the traceback stack to at least help identify the root location of the error.

Hi Ken, I don’t remember seeing a full stack like we sometimes do. Definitely nothing that might help discover the root cause. It has stung me and my team fairly often. If it’s the first time someone has seen it then they will likely be scouring settings to see which INSTALLED_APP or malformed setting is messing up Django, when it is actually an import in a package.models.

Do you know the purpose of that exception as opposed to letting it continue? Perhaps stopping an infinite recursion or something?

First, this is an area of the code that I don’t have any familiarity with. Everything I express here about it is based upon a relatively cursory review of the code.

With that disclaimer in mind, I believe that the change you show resulting in a “bad import” is a bit of a red herring.

Personally, I’m probably more concerned about irregularities in the app_configs dict as a result of concurrent or reentrant updates than a recursion error.

In general terms, if I don’t understand why Django does something, I always start from the assumption that the code is there for a reason. I personally never consider changing Django core unless I’m really confident in what effect that change will have.

Anyway, I also searched Trac to see if I could find any tickets about this issue, and the closest I could find (the only one I found) is #24523 (django.apps.registry.populate() does not handle failures in app_config.ready()) – Django

I then dug into the code and found that this was added for #21681 (Simplify Apps.populate_models) – Django

What’s this all mean? Your guess is as good as mine - but my best guess is that you’re doing something in your app config that you shouldn’t be doing.

I know this probably doesn’t help anything, but I’m really out of my depth here.