odoo/odoo · error · UserError
You can't change the company of an analytic account that alr
Error message
You can't change the company of an analytic account that already has analytic items! It's a recipe for an analytical disaster!
What it means
A constraint on account.analytic.account.company_id (_check_company_consistency). It blocks changing the company of analytic accounts that already have analytic lines whose company is not a child of the new company, because analytic lines would be left pointing at accounts of a different company.
Source
Thrown at addons/analytic/models/analytic_account.py:102
)
credit = fields.Monetary(
compute='_compute_debit_credit_balance',
string='Credit',
)
currency_id = fields.Many2one(
related="company_id.currency_id",
string="Currency",
)
@api.constrains('company_id')
def _check_company_consistency(self):
for company, accounts in groupby(self, lambda account: account.company_id):
if company and self.env['account.analytic.line'].sudo().search_count([
('auto_account_id', 'in', [account.id for account in accounts]),
'!', ('company_id', 'child_of', company.id),
], limit=1):
raise UserError(_("You can't change the company of an analytic account that already has analytic items! It's a recipe for an analytical disaster!"))
@api.depends('code', 'partner_id')
def _compute_display_name(self):
for analytic in self:
name = analytic.name
if analytic.code:
name = f'[{analytic.code}] {name}'
if analytic.partner_id.commercial_partner_id.name:
name = f'{name} - {analytic.partner_id.commercial_partner_id.name}'
analytic.display_name = name
def copy_data(self, default=None):
default = dict(default or {})
vals_list = super().copy_data(default=default)
if 'name' not in default:
for account, vals in zip(self, vals_list):
vals['name'] = _("%s (copy)", account.name)
return vals_listView on GitHub (pinned to 1e661df964)
Solutions
- First move or delete the analytic lines referencing the account (or reassign them to a company under the target)
- Create a new analytic account in the target company and move postings there instead of changing company_id
- If lines are stale/test data, archive or delete them, then retry the company change
Example fix
// before
analytic_account.write({'company_id': new_company_id})
// after
lines = env['account.analytic.line'].sudo().search([('auto_account_id', '=', account.id)])
lines.write({'company_id': new_company_id}) # or reassign
account.write({'company_id': new_company_id}) Defensive patterns
Strategy: validation
Validate before calling
def can_change_company(env, accounts, new_company):
return not env['account.analytic.line'].sudo().search_count([
('auto_account_id', 'in', accounts.ids),
'!', ('company_id', 'child_of', new_company.id),
], limit=1) Try / catch
try:
account.write({'company_id': new_co.id})
except UserError:
# move lines first, then retry
move_analytic_lines(account, new_co)
account.write({'company_id': new_co.id}) Prevention
- Prefer creating a new account in the target company over changing company_id
- Always migrate analytic lines together with account company changes
When it happens
Trigger: Calling write({'company_id': new_company_id}) on one or more analytic accounts that have account.analytic.line records via auto_account_id where those lines' company_id is outside the new company subtree. The search_count is done sudo(), so record rules do not shield it.
Common situations: Reorganizing a multi-company database (moving analytic accounts to a new company); merging companies; CSV imports or XML data that update company_id on existing analytic accounts.
Related errors
- The journal item is not linked to the correct financial acco
- The bank account of a bank journal must belong to the same c
- You can't change the company of your journal since there are
- Tax names must be unique! %(taxes)s
- You defined a distribution with analytic account(s) belongin
AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15).
Data as JSON: /api/errors/48717e64ae629ef0.
Report an issue: GitHub.