psycopg2.errors.UndefinedColumn: column company_company.spare does not exist

This error prevents manage.py makemigrations or any other operations. The workaround is to manually add a new field to the database, manually write the migration and apply it with --fake.

Django 4.2
Python 3.10
PostgreSQL 14
Windows 10 (dev) Ubuntu 22.04 (prd and staging)

The problem is obviously entirely of my own making because this is relatively recent in a three year development. It seems to follow inclusion of djstripe as a third party app.

It comes about because early in the startup process I run a query to find a particular company in the database and the additional column (company.spare) is on the Company model. Sadly I need the company instance early in the process for authorisation purposes.

I suppose I should create a separate CompanyProfile 1:1 model for such stuff. But just in case you might notice something, here is the traceback …

Australia/Melbourne: 10-9-2024 13:58:03
Performing system checks…

Exception in thread django-main-thread:
Traceback (most recent call last):
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\utils.py”, line 89, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: column company_company.spare does not exist
LINE 1: …a_reminder", “company_company”.“decrement_email”, "company_c…
^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File “C:\Python310\lib\threading.py”, line 1016, in _bootstrap_inner
self.run()
File “C:\Python310\lib\threading.py”, line 953, in run
self._target(*self._args, **self.kwargs)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\utils\autoreload.py”, line 64, in wrapper
fn(*args, **kwargs)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\commands\runserver.py”, line 133, in inner_run
self.check(display_num_errors=True)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\base.py”, line 485, in check
all_issues = checks.run_checks(
File “D:\Users\mike\envs\xxai\lib\site-packages\django\core\checks\registry.py”, line 88, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\core\checks\urls.py”, line 14, in check_url_config
return check_resolver(resolver)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\core\checks\urls.py”, line 24, in check_resolver
return check_method()
File “D:\Users\mike\envs\xxai\lib\site-packages\django\urls\resolvers.py”, line 494, in check
for pattern in self.url_patterns:
File “D:\Users\mike\envs\xxai\lib\site-packages\django\utils\functional.py”, line 57, in get
res = instance.dict[self.name] = self.func(instance)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\urls\resolvers.py”, line 715, in url_patterns
patterns = getattr(self.urlconf_module, “urlpatterns”, self.urlconf_module)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\utils\functional.py”, line 57, in get
res = instance.dict[self.name] = self.func(instance)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\urls\resolvers.py”, line 708, in urlconf_module
return import_module(self.urlconf_name)
File "C:\Python310\lib\importlib_init
.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “”, line 1050, in _gcd_import
File “”, line 1027, in _find_and_load
File “”, line 1006, in _find_and_load_unlocked
File “”, line 688, in _load_unlocked
File “”, line 883, in exec_module
File “”, line 241, in call_with_frames_removed
File “D:\Users\mike\envs\xxai\aicis\aicis\urls.py”, line 27, in
from billing import views as billing_views
File "D:\Users\mike\envs\xxai\aicis\billing\views_init
.py", line 15, in
from .stripe_views import get_test_flag, pricing_page, subscription_confirm
File “D:\Users\mike\envs\xxai\aicis\billing\views\stripe_views.py”, line 31, in
public_key, secret_key = get_stripe_keys()
File “D:\Users\mike\envs\xxai\aicis\billing\utils.py”, line 116, in get_stripe_keys
company = get_tradingco() # Climate Pty Ltd
File “D:\Users\mike\envs\xxai\aicis\billing\utils.py”, line 137, in get_tradingco
return Company.objects.get(name__istartswith=settings.TRADING)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\manager.py”, line 87, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\query.py”, line 633, in get
num = len(clone)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\query.py”, line 380, in len
self._fetch_all()
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\query.py”, line 1881, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\query.py”, line 91, in iter
results = compiler.execute_sql(
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\sql\compiler.py”, line 1562, in execute_sql
cursor.execute(sql, params)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\utils.py”, line 102, in execute
return super().execute(sql, params)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\utils.py”, line 67, in execute
return self._execute_with_wrappers(
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\utils.py”, line 80, in _execute_with_wrappers
return executor(sql, params, many, context)
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\utils.py”, line 84, in _execute
with self.db.wrap_database_errors:
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\utils.py”, line 91, in exit
raise dj_exc_value.with_traceback(traceback) from exc_value
File “D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\utils.py”, line 89, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column company_company.spare does not exist
LINE 1: …a_reminder", “company_company”.“decrement_email”, "company_c…
^
Many thanks for reading this far.

Cheers

Mike

I’m sorry, I’m a bit confused by your post here. Is there an actual issue that you are looking for assistance with?

My reading of your description is that you’ve found your fix:

Does this not cover it? (What am I missing here?)

If the issue is that you don’t like the workaround, then you do need to remove that premature query. My gut reaction is that I find it difficult to think of a situation where you need to perform any kind of automated authorization before your system is even initialized. I would think there’s some kind of more appropriate alternative available. (However, without knowing the specifics of what you’re doing, there’s no way for us to offer an alternative.)

You are correct and I should withdraw the question. Third normal form dictates the answer. I am now relocating company “settings” to a 1:1 profile table so early queries don’t interfere with migrations.

Apologies for posting before thinking.

Mike