Fix uWSGI "no python application found" for Django
Fix uWSGI no python application found, check your startup logs for errors: point module at the right wsgi.py, set chdir and virtualenv, load the Python plugin, and read the import error hidden earlier in the log.
Problem statement
uWSGI starts, Nginx proxies to it, and every request returns Internal Server Error with this in the uWSGI log:
--- no python application found, check your startup logs for errors ---
[pid: 2311|app: -1|req: -1/1] 127.0.0.1 () {44 vars in 820 bytes} [...] GET / => generated 21 bytes
uWSGI kept running even though it failed to load your Django application at startup. Unlike Gunicorn, which exits when the app cannot be imported, uWSGI logs the failure once and then answers every request with this message. The real error, a wrong module path, a missing virtualenv, or an exception in settings, is printed earlier in the log, at startup.
- Scroll up to the startup section of the uWSGI log and find the traceback or
unable to load app. - Set
module = config.wsgi:application(your project package, not a path), andchdirto the directory containingmanage.py. - Set
virtualenv(orhome) to the venv where Django is installed. - If uWSGI was installed from distro packages, add
plugins = python3. - Add
need-app = trueso uWSGI exits instead of serving errors when the app fails to load.
Step-by-step solution
1. Find the startup error
sudo journalctl -u uwsgi --since "-30min" | grep -B 5 -A 25 -iE "traceback|unable to load|ImportError|ModuleNotFound"
or the file set with logto. Typical findings:
ModuleNotFoundError: No module named 'config'
unable to load app 0 (mountpoint='') (callable not found or import error)
ModuleNotFoundError: No module named 'django'
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
Each points to a different part of the configuration below.
2. Point uWSGI at the right module and directory
# /etc/uwsgi/apps-available/myapp.ini
[uwsgi]
chdir = /srv/myapp
module = config.wsgi:application
virtualenv = /srv/myapp/.venv
env = DJANGO_SETTINGS_MODULE=config.settings.production
master = true
processes = 4
socket = /run/uwsgi/myapp.sock
chmod-socket = 660
vacuum = true
need-app = true
module is a dotted import path, resolved relative to chdir. If your project is mysite/mysite/wsgi.py with manage.py in the outer mysite, then chdir = /srv/mysite and module = mysite.wsgi:application. Using wsgi-file = /srv/mysite/mysite/wsgi.py also works but makes imports depend on the file's location.
3. Use the right virtualenv and Python
/srv/myapp/.venv/bin/python -c "import django; print(django.__version__)"
virtualenv (alias home) must point at the venv root, not its bin directory. The venv must be built with the same Python version uWSGI's plugin was compiled for. A distro uWSGI with a Python 3.11 plugin cannot load a venv built with Python 3.12; install uWSGI into the venv with pip instead, which builds it against that Python.
4. Load the Python plugin
Distribution packages (apt install uwsgi) ship a core binary with plugins. Without the Python plugin, options like module are unknown:
plugins = python3
and install the plugin package (uwsgi-plugin-python3). uWSGI installed with pip includes Python support and needs no plugin line.
5. Provide environment variables
If settings read secrets from the environment, the uWSGI service needs them. Use env = KEY=value lines for non-secrets and an environment file for secrets in the systemd unit:
[Service]
EnvironmentFile=/etc/myapp/env
ExecStart=/srv/myapp/.venv/bin/uwsgi --ini /etc/uwsgi/apps-available/myapp.ini
6. Fail fast with need-app
need-app = true
With this option uWSGI exits at startup if the app fails to load, so systemd reports a failed service and your deploy notices immediately, instead of a running server that returns errors to every visitor.
Verification check:
sudo systemctl restart uwsgi
sudo journalctl -u uwsgi -n 30 | grep -E "WSGI app 0|spawned uWSGI worker"
curl -sI http://example.com | head -1
A successful load logs WSGI app 0 (mountpoint='') ready.
Explanation
uWSGI was designed to host many applications and to keep running even if one fails, so a failed import is logged and the worker continues with no application mounted. Every request then hits the fallback that prints "no python application found". This design is helpful for multi-app emperor setups and confusing for a single Django project. need-app reverses the behaviour, matching what most deployments expect: no app, no server.
Edge cases / notes
- Emperor mode loads vassal configs from a directory; check the vassal's own log, not just the emperor's.
- Lazy apps. With
lazy-apps = true, each worker imports the app itself; errors appear per worker. - Python 3.12+ removed
distutils, which some old uWSGI builds needed. Use uWSGI 2.0.22 or newer. - Maintenance status. uWSGI is in maintenance mode; for new projects, Gunicorn or Granian is usually simpler.
Next steps
- Review a complete setup in Deploy Django With uWSGI and Nginx.
- The Gunicorn equivalent is Fix Gunicorn Failed to Find Application Object.
FAQ
Where is the real error?
In the uWSGI startup log, before the first request. The per-request line only says no app was loaded.
Should I use module or wsgi-file?
module with chdir is clearer for Django projects and matches how manage.py imports the project.
Why does uWSGI keep running if the app failed?
It is built to host several apps. Set need-app = true to make it exit instead.
Do I need plugins = python3?
Only for distribution-packaged uWSGI. A pip-installed uWSGI includes Python support.