Odoo upgrade error

time zone "Asia/Calcutta" not recognized

Last updated: October 2026

Older Odoo versions offered legacy time zone names. Newer Linux images no longer install them, so PostgreSQL and Python stop recognizing values your database already stores.

This page is part of our guide on how to upgrade Odoo Community Edition. It explains what triggers the error, how to fix it by hand, and what an automated migration does about it.

The error

psycopg2.errors.InvalidParameterValue: time zone "Asia/Calcutta" not recognized

From Python code the same problem shows up as pytz.exceptions.UnknownTimeZoneError: 'Asia/Calcutta'. Other legacy names behave the same way, for example US/Eastern, Asia/Saigon or Europe/Kiev.

Raised by
PostgreSQL (AT TIME ZONE) or pytz.timezone()
Affected setups
Odoo or PostgreSQL on Ubuntu 24.04 without tzdata-legacy, including the odoo:18.0 and odoo:19.0 Docker images
Upgrade hops
Seen on 18→19; can appear in any version on such a server

When you see it

Asia/Calcutta is an old alias of Asia/Kolkata. Odoo builds its time zone list from pytz, so older Odoo versions offered the alias and users picked it for themselves, their company partner or a working-hours calendar. The value is stored as plain text in columns such as res_partner.tz, resource_calendar.tz and resource_resource.tz.

Ubuntu 24.04 moved these aliases out of the tzdata package into a separate tzdata-legacy package that is not installed by default. PostgreSQL on Debian and Ubuntu reads the system time zone database, and so does the distribution's python3-tz. On such a system any SQL that converts with a stored zone fails. Odoo 19 does this itself, for example when it computes the state of activities from mail_activity.user_tz. Migration scripts that convert dates into an employee's local time hit it too: we traced a failed 18→19 run to exactly this, while computing HR work entry dates.

Root cause

The data is valid; the server is missing the names. Check which legacy values your database holds:

SELECT tz, count(*) FROM res_partner
WHERE tz IN ('Asia/Calcutta', 'Asia/Saigon', 'Asia/Katmandu',
             'US/Eastern', 'US/Central', 'US/Pacific')
GROUP BY tz;

And check whether PostgreSQL knows a name:

SELECT now() AT TIME ZONE 'Asia/Calcutta';

How to fix it

Option 1: install the legacy names on the server

On the machine or container that runs PostgreSQL, and on the one that runs Odoo if it is different:

apt-get update
apt-get install tzdata-legacy

Restart PostgreSQL and Odoo afterwards. This changes no data and fixes every legacy name at once. If you run the official Odoo Docker image, add the package in your own Dockerfile so it survives image updates.

Option 2: switch the data to canonical names

This makes the database independent of the server packages. Odoo stores time zones in several tables, so update every column that holds one:

Before you change anything: Back up the database before running any UPDATE or INSERT below, and try it on a copy first. These statements change data directly, outside the Odoo ORM.

DO $
DECLARE
  r record;
  m record;
BEGIN
  FOR m IN SELECT * FROM (VALUES
      ('Asia/Calcutta', 'Asia/Kolkata'),
      ('Asia/Saigon',   'Asia/Ho_Chi_Minh'),
      ('Asia/Katmandu', 'Asia/Kathmandu'),
      ('US/Eastern',    'America/New_York'),
      ('US/Central',    'America/Chicago'),
      ('US/Pacific',    'America/Los_Angeles')
    ) AS t(old_tz, new_tz)
  LOOP
    FOR r IN
      SELECT c.table_name, c.column_name
      FROM information_schema.columns c
      JOIN information_schema.tables t
        ON t.table_schema = c.table_schema AND t.table_name = c.table_name
      WHERE c.table_schema = 'public'
        AND t.table_type = 'BASE TABLE'
        AND c.column_name IN ('tz', 'user_tz', 'date_tz', 'event_tz', 'timezone')
        AND c.data_type IN ('character varying', 'text')
    LOOP
      EXECUTE format('UPDATE %I SET %I = %L WHERE %I = %L',
                     r.table_name, r.column_name, m.new_tz,
                     r.column_name, m.old_tz);
    END LOOP;
  END LOOP;
END $;

Extend the list with any other legacy names the first query found. Doing both options is the safest choice: the package for anything you missed, the data change for the long run.

How OCU handles it

Since the end of September 2026 the OCU runner images install tzdata-legacy, so the embedded PostgreSQL and Python resolve legacy names during the migration and the upgrade no longer fails on them. An image-level test checks this for each runner version.

OCU does not rewrite the stored values. The migrated database still contains Asia/Calcutta where your users chose it, so if your new Odoo server is based on Ubuntu 24.04, apply option 1 or option 2 there.

A free test migration shows whether your database runs into this or any other upgrade error before you change anything on your production server.

Frequently asked questions

Is Asia/Calcutta a wrong time zone?
No. It is an official alias of Asia/Kolkata in the IANA time zone database and gives the same offset. It is only missing because some Linux distributions no longer install the alias names by default.
Why does the error only appear after moving to a new server?
Older server images installed the alias names as part of tzdata. Ubuntu 24.04 moved them into the tzdata-legacy package, so a database that worked on the old server fails as soon as PostgreSQL or Python on the new server needs to resolve the stored name.
Do I need to change anything in Odoo itself?
No code change is needed. Either install tzdata-legacy on the server or update the stored values to the canonical names. Users can also pick the canonical zone in their preferences afterwards.

Related

Find upgrade errors before your production run

Upload a backup and run a free test migration. You get the upgraded database, the full log and every warning, with no change to your live system.

Start your free test migration