Fix Heroku "Error While Running collectstatic" for Django
Fix the Heroku Python build error while running python manage.py collectstatic --noinput: read the hidden traceback, set STATIC_ROOT, avoid settings that need runtime config vars at build time, and fix WhiteNoise manifest errors.
Problem statement
git push heroku main builds dependencies and then fails:
remote: ! Error while running '$ python manage.py collectstatic --noinput'.
remote: See traceback above for details.
remote:
remote: You may need to update application code to resolve this error.
remote: Or, you can disable collectstatic for this application:
remote:
remote: $ heroku config:set DISABLE_COLLECTSTATIC=1
remote:
remote: ! Push rejected, failed to compile Python app.
The Heroku Python buildpack runs collectstatic automatically during the build. Any exception, from settings import to a missing file referenced in CSS, fails the whole push. The actual error is a few dozen lines above this message; the summary only tells you the step that failed.
- Scroll up in the build output to the Python traceback; that is the real error.
- Set
STATIC_ROOT = BASE_DIR / "staticfiles"if the error says it is not set. - Avoid reading config vars that are missing at build time; use defaults for settings not needed by collectstatic.
- For WhiteNoise "could not be found" errors, fix the CSS or JS that references a missing file.
- Reproduce locally with production settings:
DJANGO_SETTINGS_MODULE=... python manage.py collectstatic --noinput.
Step-by-step solution
1. Read the traceback
Run the build again and keep the full output, or open the failed build in the Heroku dashboard under Activity. Look for the last Python exception before the summary:
django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app
without having set the STATIC_ROOT setting to a filesystem path.
ValueError: The file 'img/hero.webp' could not be found with
<whitenoise.storage.CompressedManifestStaticFilesStorage object at 0x7f...>.
KeyError: 'DATABASE_URL'
Each points to a different fix.
2. Set STATIC_ROOT and storage
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STORAGES = {
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
}
Add whitenoise.middleware.WhiteNoiseMiddleware right after SecurityMiddleware. Without a static server, Heroku cannot serve the collected files.
3. Handle config vars at build time
Heroku makes config vars available during the build, but add-ons attached later, review apps, and pipelines can leave some unset. Settings that read them with os.environ["X"] fail at import, before collectstatic even starts. Give non-essential settings defaults, or load them lazily:
DATABASES = {"default": dj_database_url.config(conn_max_age=60, default="sqlite:///:memory:")}
SENTRY_DSN = os.environ.get("SENTRY_DSN", "")
collectstatic does not touch the database, so a placeholder default is harmless during the build. Keep SECRET_KEY required, and set it as a config var.
4. Fix missing referenced files
CompressedManifestStaticFilesStorage rewrites url() references in CSS and import statements in JavaScript modules to hashed names. If a referenced file does not exist, it raises. Fix the path in the stylesheet, add the missing file, or, if a third-party CSS file references files you do not ship, set:
WHITENOISE_MANIFEST_STRICT = False
This only affects {% static %} lookups at runtime. For post-processing errors, the targeted fix is to correct the reference.
5. Disable automatic collectstatic only on purpose
DISABLE_COLLECTSTATIC=1 skips the step, which is useful when a frontend build creates assets in a later build step or when static files go to S3 in a release phase. Without a replacement, your site will have no CSS. Run it yourself in bin/post_compile or a release command instead.
Explanation
The buildpack runs collectstatic so that static files are part of the slug, the compressed image Heroku boots on every dyno. Collecting at runtime would be too slow and repeated per dyno. Because the command imports your full settings and every installed app, any import-time error in the project surfaces here first. That is why "collectstatic failed" often has nothing to do with static files.
Edge cases / notes
- Node assets. If you build CSS or JS with npm, add the Node.js buildpack before the Python one so assets exist when
collectstaticruns. - Cached builds. Clearing the build cache (
heroku builds:cache:purge) helps when an old cached package causes the error. - Review apps. Review apps need the same config vars; set them in
app.json.
Next steps
- For collectstatic errors on any platform, see Fix collectstatic Errors in Django.
- Manifest problems at runtime are covered in Fix Missing staticfiles Manifest Entry.
- Review the full setup with Deploy Django on Heroku.
FAQ
Can I just set DISABLE_COLLECTSTATIC=1?
It lets the push succeed, but your site then has no static files unless you collect them another way. Fix the error instead.
Are config vars available during the Heroku build?
Yes, app config vars are available to the build. Add-on variables attached after the build, or missing variables in review apps, can still be absent.
Why does collectstatic fail with a database error?
Usually a setting or app runs a query at import time. Move such code into functions or AppConfig.ready() with care.
Do I need WhiteNoise on Heroku?
Yes, or another way to serve static files such as a CDN. Heroku does not serve files from the slug automatically.