How to avoid "ValueError: year is out of range" error when fetching models?

I’m upgrading an app (Django 2.2, PostgreSQL 10) to latest versions (Django 4.2, PostgreSQL 15), and most things are working, but I get ValueError: year ..... is out of range errors when the year is more than 5 digits.

I wholeheartedly agree with the conclusion (i.e., wontfix) of issue #10408 as the database entry in our case should have never been created and clearly wrong, but I wonder how I could make the upgraded app behave like the old one: The database query still runs without errors and the page for the item simple shows year: 9999 (the actual value is 20216).

I presume the issue may during converting the returned row that has a date PostgreSQL type column (where range of valid years are between 4713 BC and 5874897 AD) to Python datetime, but can’t figure out why this wasn’t an issue for Django 2.2.

I’m basing this assumption on google searches and the fact that model query fails on the Django shell,

from my_app.models import MyModel

p = MyModel.objects.get(pk=17615)

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/query.py", line 633, in get
    num = len(clone)
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/query.py", line 380, in __len__
    self._fetch_all()
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/query.py", line 1881, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/query.py", line 91, in __iter__
    results = compiler.execute_sql(
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1593, in execute_sql
    return list(result)
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 2091, in cursor_iter
    for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel):
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 2091, in <lambda>
    for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel):
  File "/home/toraritte/my_project/venv/lib/python3.10/site-packages/django/db/utils.py", line 98, in inner
    return func(*args, **kwargs)
ValueError: year 20216 is out of range

but the generated SQL statement works without an issue.


Just putting this here for future self:

>>> from django.db import connection
>>> connection.queries[-1]['sql']

Do you need to keep this values?

Because you can connect to Postgres directly and make a bulk update of the wrong values.

1 Like

This is what I did, but it’s just treating the symptom. The project wasn’t written by me, so I’m still trying to figure out how this value could have ended up in the database in the first place. The real solution would be checking the input in the forms, add constraints, etc.

Nonetheless, my main concern is that when reading a valid value from the database (again, the value of PostgreSQL’s date type can be between 4713 BC and 5874897 AD), Django 4.2 throws an error because models.DateField is represented by datetime.date where

datetime.MAXYEAR
The largest year number allowed in a date or datetime object. MAXYEAR is 9999.

I’m new to Django (even to Python), so maybe I missed something in the docs, but right now it looks that if I was to save fictional dates (e.g., for a Warhammer 40k campaign), Django wouldn’t be able to fetch them, unless they are saved as a different type. Feels wrong to compromise the integrity of the data to conform to the UI, but then again, I’m probably missing something obvious.