Unknown command - out of nowhere

I’ve been working on my project and suddenly builds started breaking at ‘python manage.py collectstatic’. Error being ‘Unknown command’.
I have a bunch of clues but ultimately they amount to nothing.
The command still work with ‘local’ DJANGO_SETTINGS_MODULE, but with ‘production’ it doesn’t.
Actually, when running the ‘diffsettings’ command, it seems that they aren’t read at all. With ‘local’ it outputs all the settings, but with ‘production’ it only outputs the DJANGO_SETTINGS_MODULE set to ‘production’ (it’s actually folder.folder.production, and nothing has changed so the issue isn’t with incorrect Django settings module path value)

There are no other errors. I actually follow through and it seems that all settings are read as usual during django.setup(), but then somehow lost by the time the command is called.

There’s another manage.py command that outputs all available commands are there are none in that case. So I understand that it breaks because of that, but I don’t see a reason for it. I reviewed git commits and there were no meaningful changes that could affect it IMHO.

I revised project dependencies and before the collect static the .venv is prepared exactly the same way before the error and after. I compared logs of a couple of builds and even all of the dependency versions and they’re identical. Every single one. Additionally, there were no new dependencies added to the project. So that is not the issue.

What could be the issue?

I’ll edit and add some logs but I don’t expect them to reveal anything at this point. I’m reaching out if maybe anyone else who understand the under the hood workings of Django better to maybe chip in because I’m clueless.

Unsuccessful build step:
2025-04-01T10:44:58.2692002Z ##[group]Run export DJANGO_SETTINGS_MODULE=GroveIQ.django.production
export DJANGO_SETTINGS_MODULE=GroveIQ.django.production
python manage.py collectstatic --noinput
shell: /usr/bin/bash -e {0}
env:
UV_PYTHON: 3.12.9
VIRTUAL_ENV: /home/runner/work/IQMonitor/IQMonitor/.venv
UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
RUFF_OUTPUT_FORMAT: github
Unknown command: ‘collectstatic’
/home/runner/work/IQMonitor/IQMonitor/.venv/bin/python
GroveIQ.django.production
BASE_DIR=/home/runner/work/IQMonitor/IQMonitor
PRODUCTION MODE ENABLED
Type ‘manage.py help’ for usage.
Process completed with exit code 1.

Successful build step just before:
2025-04-01T05:14:25.3691381Z ##[group]Run export DJANGO_SETTINGS_MODULE=GroveIQ.django.production
export DJANGO_SETTINGS_MODULE=GroveIQ.django.production
python manage.py collectstatic --noinput
shell: /usr/bin/bash -e {0}
env:
UV_PYTHON: 3.12.9
VIRTUAL_ENV: /home/runner/work/IQMonitor/IQMonitor/.venv
UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
RUFF_OUTPUT_FORMAT: github
/home/runner/work/IQMonitor/IQMonitor/.venv/bin/python
GroveIQ.django.production
BASE_DIR=/home/runner/work/IQMonitor/IQMonitor
PRODUCTION MODE ENABLED

177 static files copied to ‘/home/runner/work/IQMonitor/IQMonitor/staticfiles’.

The general idea how my project is set up is base.py for general settings. At the bottom of it I import some settings for dependencies, and in local.py and production.py I ‘from .base import *’
There are no errors that I can see or that Django would raise an issue with, and nothing really changed between commits that we’re built successfully and those that followed that failed like explained above.

Like I said, I went through with the debugger and the settings are read in its entirety but then before the command is invoked they’re all gone and it fails. Also, the contrib.static is still included in the INSTALLED_APPS, so, idk … But it’s not an issue with contrib static as none of the settings end up there when it breaks… :person_shrugging:

Is anyone familiar with a potential issue that could cause this?

What could cause this?

I frickin found it…

So… it all comes down to basically trying to read an env variable that does not exist…

I had to checkout revisions and test with a special run configuration and then literally go through changes and it still didn’t occur to me until I had it right in front of my face…

I’m using ‘django-environ’ and it’s really nice tbh, …

I have dev environment set up with a docker compose file that brings all dependencies up and then I restart django from inside pycharm.
but in production django is part of the stack… I have a docker compose file to build the images and then a deploy script that pulls them and uses the other docker compose file that uses those pulled images and brings the entire stack up…
so, in dev, I need to refer to service host inside docker container with 127.0.0.1, but in production it’s sufficient to only use ‘db’ or ‘redis’, etc… but in production db is actually not in the compose stack, but on another VM entirely…

so, here’s the problematic code:
RUNNING_IN_DOCKER = os.path.exists(‘/.dockerenv’)
if RUNNING_IN_DOCKER:
DATABASE_HOST = env.str(“DATABASE_HOST_DOCKER”)
REDIS_HOST = env.str(“REDIS_HOST_DOCKER”) # from .env.dev

else:
DATABASE_HOST = env.str(“DATABASE_HOST_DEFAULT”)
REDIS_HOST = env.str(“REDIS_HOST_DEFAULT”) # from .env.dev

and then below I update whatever was set above to the correct value:
CELERY_BROKER_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB_CELERY}"
DJANGO_REDIS_CACHE_LOCATION = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB_CACHE}"
CACHES[‘default’][‘LOCATION’] = DJANGO_REDIS_CACHE_LOCATION
DATABASES[‘default’][‘HOST’] = DATABASE_HOST

at the bottom of my base.py I sort this out with the code above. but I only updated .env.dev and forgot to update .env.prod,…

.env.dev:
DATABASE_HOST_DOCKER=db
DATABASE_HOST_DEFAULT=127.0.0.1

.env.prod: still had this:
DATABASE_HOST=‘some-hostname.lol’

and I basically had to replace it with:
DATABASE_HOST_DOCKER=‘some-host.lol’
DATABASE_HOST_DEFAULT=127.0.0.1

and then it started working again… what a mess man… it would really be great if it complained about this. Is there a way to ask django-environ to list any env variables that are missing in the environment?
This could be useful to spot such issues.

Anyways… can’t really brag about how well was I debugging this but it was odd, because like I said, all settings firstly seem available but then after django.setup() it returns in django/apps/core/management/commands/init.py inside def autocomplete(

I’m using django 5.1.7, but that’s irrelevant.

Peace.