Forums

Django Logging Recursion on New Instance

I recently migrated a Django web app from one PythonAnywhere instance to another (same codebase, new environment).

Expected Behaviour

Django should log warnings/error normally without affecting request handling

Actual Behaviour

On the new instance, any Django warning triggers a logging loop that results in:

RecursionError: maximum recursion depth exceeded while calling a Python object

From the traceback, the recursion appears to follow this pattern:

logging → stream.write → logger.error → logging → ...

Specifically, it looks like logging is writing to a stream wrapped by:

/bin/user_wsgi_wrapper

whose write() method calls logger.error(), causing infinite recursion.

This behaviour did not occur on the previous instance.

Steps Taken to Stabilise

  • Adjusted Django logging configuration to avoid problematic handlers
  • Temporarily suppressed warnings in the WSGI file

However, I’d like to properly understand:

  • Whether stdout/stderr is expected to be wrapped this way on this instance
  • Why this behaviour differs from my previous instance
  • What the recommended logging configuration is to avoid this recursion (e.g. avoiding StreamHandler entirely)

Happy to provide full traceback or for PythonAnywhere Staff to access my codebase if needed.

Thanks in advance

I see that both of your web apps are working now, so I'm guessing you worked out what the problem was.

Hi Glenn,

No, as mentioned they're working because I've had to suppress warnings in my WSGI file, and create a root logger to avoid problematic handlers (after getting tired of having to reactively change each time a recursion error hit).

It doesn't make sense,.as it's the same code in my other instance (user name davidwaugh).

I'd really appreciate this being looked in to for me so I no longer have to suppress warnings and can have a more straightforward logging config.

The issue is that, when it is trying to log, that fails, which tries to log that it fails and that results in the repeated failures.

My guess would be that your logging config is ok for the old account, but incorrect for the new account in some way.

Thanks Glenn,

I understand the recursion occurs because logging itself is failing and then attempting to log that failure recursively.

What I’m struggling to reconcile is that the application codebase and logging configuration were functioning without issue on the previous PythonAnywhere instance, and the recursion only began after migration to the new environment.

At this point I’ve had to:

  • suppress warnings in WSGI
  • explicitly disable propagation for multiple third-party loggers
  • Introduce a restrictive root logger configuration

…purely to prevent warning-level events from recursively failing through the wrapper.

The reason I raised this is that the recursion path consistently appears to involve the WSGI stream wrapper (user_wsgi_wrapper.py) writing back into logging during stream failure handling.

So I’m mainly trying to understand:

  • whether stdout/stderr wrapping behaviour differs between instances or Python versions
  • whether there are environment-level differences in how logging streams are handled
  • whether this recursion pattern is considered expected behaviour when StreamHandler interacts with the wrapper

I completely accept that my logging configuration needed tightening, but I’d appreciate clarification on why the same configuration was stable on the previous instance and catastrophically recursive on the new one.

I’m mainly trying to determine whether this is something that can be resolved through configuration hardening on my side, or whether there are environment/platform differences I should be accounting for going forward.

Thanks again for taking a look.

Hi team,

Just following up on this issue, as I haven’t heard back since my last message a few days ago.

I’m still seeing the behaviour where warnings appear to trigger failures/errors in the production environment, particularly during PDF generation and related processing. I’ve done what I can application-side to reduce and suppress warnings, but I’m trying to understand whether there’s any platform-level behaviour or configuration contributing to this.

Could someone please take another look when possible?

Thanks, Dan

Could you clarify if you still see recursion errors or some other warnings?

Hi,

Yes — still seeing recursion errors.

The underlying warnings themselves are generally harmless (for example xhtml2pdf parsing unsupported percentage-based sizing during PDF generation), however on this instance they appear to recurse through /bin/user_wsgi_wrapper.py until the request crashes with:

RecursionError: maximum recursion depth exceeded while calling a Python object

The application is currently only stable because I’ve had to suppress warnings in WSGI, disable propagation on several third-party loggers, and heavily restrict the root logger configuration.

What I’m trying to understand is why the same codebase and logging configuration behaved normally on the previous instance, but recursively fails on this one.

Specifically:

  • does stdout/stderr wrapping differ between environments?
  • is StreamHandler expected to interact safely with the wrapper?
  • is this recursion behaviour considered expected when logging fails inside the wrapper?

I’m happy to further harden the logging configuration on my side — I’m mainly trying to understand the environment/platform difference that introduced the behaviour.

Thanks, Dan

Hi team,

Commenting from the legacy instance/account referenced above (davidwaugh) just to confirm this is the original environment the application was migrated from. The web app under the standard user domain.

The same application and logging configuration operated for years without recursive logging failures on this instance. The recursion behaviour only appeared after migration to the new environment/account.

Hopefully that helps narrow down whether there are any environment/runtime differences contributing to the issue.

Thanks, Dan

One additional note for context:

We were also able to reproduce a very similar recursive logging / stack overflow failure in staging after upgrading the Python runtime on that instance.

So while this may be runtime-version-sensitive, it does appear to indicate there may be an underlying compatibility or recursion issue that is surfaced under the newer environment/runtime configuration.

Happy to provide additional logs if useful.

That probably means that the code is not suited to the environment and so it produces errors that lead to the recursive error logging.

I understand the position that the application logging setup may contain an incompatibility exposed by the newer runtime/environment.

However, from my perspective, the unresolved issue is that the same codebase and logging configuration operated without recursive failures for years on the previous PythonAnywhere environment, and I still don’t have a clear explanation of what behavioural/runtime difference introduced the change.

At the moment the responses seem limited to 'the app is not suited to the environment', without any concrete detail on what specifically changed between environments or runtimes.

That makes it difficult to confidently operate or migrate production workloads on the platform going forward, particularly when diagnosing environment-sensitive regressions like this.

If there's no additional detail available around the runtime/wrapper behaviour differences, then I'll likely continue moving workloads toward platforms where the runtime environment is more transparent and reproducible.

We have not made any changes to it. It is rather one of the dependencies of your code or the python that was upgraded.