The Error
You pushed a new version to Elastic Beanstalk and the deployment cratered. The EB console flips to Severe, and the events log is spitting out something like:
ERROR: Your WSGIPath refers to a file that does not exist.
Instance deployment failed. For details, see 'eb-engine.log'.
Environment health has transitioned from Ok to Severe
Often this comes bundled with load balancer health check failures โ the LB keeps hitting your instances, gets nothing but errors back, and EB marks them unhealthy. The environment spirals from Ok โ Warning โ Severe in under two minutes.
Two separate problems, but they're linked. Fix the WSGI misconfiguration first. The health check failures almost always sort themselves out once the app actually starts.
Why This Happens
EB needs to know where your WSGI callable lives. It looks for this via .ebextensions, a Procfile, or the aws:elasticbeanstalk:container:python namespace. If that path doesn't match what's in your deployment zip, the app server โ Apache + mod_wsgi on Amazon Linux 2, or gunicorn on AL2023 โ never starts.
The usual culprits:
WSGIPathstill points toapplication.py, but you renamed or restructured the project- Django project deployed without setting the path to
myproject/wsgi.py .ebignoreor.gitignoreis silently excluding the wsgi file from the bundle- CI/CD packaging mistake โ the zip uploaded to S3 is missing the file entirely
- Health check path returns a redirect (301/302) or an auth wall instead of 200
Step 1 โ Read the Logs Before Touching Anything
Guessing wastes deploys. Pull the logs first:
# Via EB CLI
eb logs
# Or stream in real time
eb logs --stream
Focus on two files: eb-engine.log shows exactly which path EB tried to load. web.stdout.log shows what happened when the app server actually tried to start โ import errors, missing environment variables, that sort of thing.
Prefer clicking? Go to Environment โ Logs โ Request Logs โ Last 100 Lines in the console.
Step 2 โ Fix the WSGIPath
Check what path EB is currently configured to use:
eb config
This opens your environment config in an editor. Find this section:
aws:elasticbeanstalk:container:python:
WSGIPath: application:application
The format is module_path:callable for a Python object, or a plain file path for Django's wsgi.py. Here's what the correct value looks like for common setups:
Flask (single file)
# application.py contains: app = Flask(__name__)
aws:elasticbeanstalk:container:python:
WSGIPath: application:app
Django
aws:elasticbeanstalk:container:python:
WSGIPath: myproject/wsgi.py
Swap myproject for your actual Django project folder โ the one that has settings.py in it, not the repo root.
The cleanest way to manage this is version-controlling it in .ebextensions/python.config:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: myproject/wsgi.py
NumProcesses: 1
NumThreads: 15
That way the correct path ships with every deploy, and you're not relying on environment config that someone might accidentally overwrite.
For Django, also make sure the settings module is set:
eb setenv DJANGO_SETTINGS_MODULE=myproject.settings
Step 3 โ Verify the File Is Actually in the Deployment Bundle
When you run eb deploy, EB zips your project using git โ which means it respects .gitignore. If the wsgi file isn't tracked, it doesn't ship.
# Check what EB would actually include
git ls-files | grep wsgi
No output? The file isn't tracked. Either commit it, or override the exclusion with .ebignore:
# .ebignore โ force-include even if .gitignore excludes it
!myproject/wsgi.py
Building a zip manually in CI/CD? Verify its contents directly:
unzip -l deploy.zip | grep wsgi
This catches a surprisingly common CI mistake where the packaging step runs from the wrong directory and produces a zip with the wrong structure inside.
Step 4 โ Fix the Health Check Path
The app might be running fine, but the load balancer still marks instances unhealthy. By default, EB hits / every 30 seconds. If that path redirects (say, to a login page) or returns anything other than 2xx, the check fails.
Add a dead-simple health endpoint that always returns 200:
# Flask
@app.route('/health')
def health():
return 'OK', 200
# Django (urls.py)
from django.http import HttpResponse
urlpatterns = [
path('health/', lambda request: HttpResponse('OK')),
# ... rest of your urls
]
Then point EB at it. In the console: Configuration โ Load Balancer โ Processes โ Health check path โ /health.
Or in .ebextensions:
option_settings:
aws:elasticbeanstalk:application:
Application Healthcheck URL: /health
Step 5 โ Redeploy and Watch
eb deploy --staged
Tail the events as it runs:
eb events -f
Deployment succeeded but health is still Severe? Wait it out โ EB requires several consecutive successful health checks (typically 3 in a row, ~90 seconds apart) before flipping back to Ok.
Verification
You're done when all three of these are true:
- Console shows Health: Ok (green)
eb statusreportsHealth: Green- The app URL responds correctly
eb status
# Expected:
# Environment details for: your-env-name
# Status: Ready
# Health: Green
curl -I https://your-env.elasticbeanstalk.com/health
# Expected: HTTP/1.1 200 OK
Quick Reference โ Common WSGIPath Values
- Flask (application.py โ app):
application:app - Flask (application.py โ application):
application:application - Django:
myproject/wsgi.py - FastAPI with Mangum:
main:handler(though FastAPI typically runs on Lambda, not EB)
Still Failing? SSH In
If everything above checks out and deploys still die, go straight to the instance:
eb ssh
# Check the app server process
sudo systemctl status web
# Read the engine log directly
sudo tail -50 /var/log/eb-engine.log
Nine times out of ten, what you'll find is a missing environment variable โ SECRET_KEY for Django is the classic example. The app crashes on startup, never serves a single request, and EB reports the whole thing as a health check failure. The real error is buried in web.stdout.log, not the health check events.

