Odoo upgrade error
ValueError: External ID not found in the system
Last updated: October 2026
Code or data refers to a record by external ID and the database has no record under that name. During upgrades the usual causes are renamed or removed IDs.
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
ValueError: External ID not found in the system: account.1_pcg_707_accountThe ID after the colon is module.name. It tells you which record is missing and which module expects it.
- Raised by
ir.model.data._xmlid_lookup(behindenv.ref()andref=in XML)- Upgrade hops
- Any; the chart of accounts case shows up on 17→18 and 18→19
- Seen when
- Loading data files or running a module's migration script
Read the external ID first
Every record created from a module's data has an external ID, stored in ir_model_data as module plus name. XML files and Python code look records up by that ID. The error means the lookup found nothing. Check what the database has under similar names:
SELECT module, name, model, res_id, noupdate
FROM ir_model_data
WHERE name LIKE '%pcg_707%'
ORDER BY module, name;What you find decides which of the three cases below applies.
Case 1: chart of accounts IDs under the old module name
Up to Odoo 16, loading a chart of accounts created each company's accounts, taxes, fiscal positions and account groups with external IDs in the localization module, such as l10n_fr.1_pcg_707_account (1 is the company id). Since Odoo 17 the chart loader and the localization migration scripts look for them under account: account.1_pcg_707_account. A database upgraded from 16 without moving the IDs still works day to day, but when an Odoo 18 or 19 localization migration reloads the chart, it cannot find its own accounts. We traced a French 16→19 failure to this: it needed an older chart without account 707000 and a subsidiary company without its own chart.
If the SELECT shows the ID under an l10n_* module, move the per-company CoA IDs to account. This is the same step OpenUpgrade performs in its Odoo 17 account migration:
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.
UPDATE ir_model_data d
SET module = 'account'
WHERE d.module LIKE 'l10n\_%'
AND d.model IN ('account.account', 'account.tax',
'account.fiscal.position', 'account.group')
AND d.name ~ '^[0-9]{1,9}_'
AND split_part(d.name, '_', 1)::int IN (SELECT id FROM res_company)
AND NOT EXISTS (SELECT 1 FROM ir_model_data e
WHERE e.module = 'account' AND e.name = d.name);Run it on the Odoo 17 database (or the 17 copy you upgrade from), then repeat the upgrade from there.
Case 2: a record you deleted
If nothing similar exists, someone may have deleted a standard record that another module's data refers to, such as a default journal, product category or security group. Restore it from a backup of the old database, or recreate it and add the external ID by hand with an INSERT INTO ir_model_data row that points at the new record.
Case 3: a custom or third-party module
If the missing ID belongs to a standard module and the error is raised while loading a custom module, that module refers to a record the new Odoo version removed or renamed. Use the module version written for the target release, or fix its XML and Python references. Removing a module from the upgrade is also an option if you no longer need it.
How OCU handles it
On the 16→17 hop OCU moves the per-company chart of accounts IDs from the localization namespace to account (accounts, taxes, fiscal positions, account groups), matching OpenUpgrade. The 17→18 and 18→19 hops repeat the move as a safety net for databases that reached those versions through other tools. On 17→18 OCU also makes sure subsidiary companies without their own chart inherit the parent's chart template, which the localization migrations rely on.
Third-party modules whose code is not in the target version are not loaded during the OCU upgrade, so their data files cannot raise this error during the run. Their references still need updating when you install their new versions.
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
- Can I create a dummy record to satisfy the lookup?
- Only when you understand what the record is used for. A fake account or tax created only to silence the error can end up on invoices. Moving or restoring the real external ID is the safer fix.
- Why does the error appear in a localization module I did not touch?
- Several Odoo 18 and 19 localization modules (for example the French one) ship migration scripts that reload the chart of accounts. Those scripts look up accounts by their account.* external IDs, so a database whose IDs still sit in the l10n_* namespace fails inside them.
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