odoo/odoo · error · UserError
You cannot delete this account tag (%s), it is used on the c
Error message
You cannot delete this account tag (%s), it is used on the chart of account definition.
What it means
Raised by the @api.ondelete guard _unlink_except_master_tags on account.account.tag. Three XML-ID master tags (account_tag_operating, account_tag_financing, account_tag_investing) drive the cash-flow statement columns in the chart-of-accounts/report definitions; deleting them would break the standard reports, so Odoo refuses.
Source
Thrown at addons/account/models/account_account_tag.py:120
return self.env['account.report.expression'].search(Domain('engine', '=', 'tax_tags') & Domain.OR(
(
Domain('report_line_id.report_id.country_id', '=', record.country_id.id)
& Domain('formula', 'in', (record.name, '-' + record.name))
)
for record in self
))
@api.ondelete(at_uninstall=False)
def _unlink_except_master_tags(self):
master_xmlids = [
"account_tag_operating",
"account_tag_financing",
"account_tag_investing",
]
for master_xmlid in master_xmlids:
master_tag = self.env.ref(f"account.{master_xmlid}", raise_if_not_found=False)
if master_tag and master_tag in self:
raise UserError(_("You cannot delete this account tag (%s), it is used on the chart of account definition.", master_tag.name))
def _translate_tax_tags(self, langs=None, tag_ids=None):
"""Translate tax tags having the same name as report lines."""
langs = langs or (code for code, _name in self.env['res.lang'].get_installed() if code != 'en_US')
for lang in langs:
self.env.cr.execute(SQL(
"""
UPDATE account_account_tag tag
SET name = tag.name || jsonb_build_object(%(lang)s, substring(tag.name->>'en_US' FOR 1) || (report_line.name->>%(lang)s))
FROM account_report_line report_line
JOIN account_report report ON report.id = report_line.report_id
WHERE tag.applicability = 'taxes'
AND tag.country_id = report.country_id
AND tag.name->>'en_US' = substring(tag.name->>'en_US' FOR 1) || (report_line.name->>'en_US')
AND tag.name->>%(lang)s != substring(tag.name->>'en_US' FOR 1) || (report_line.name->>%(lang)s)
%(and_tag_ids)s
""",
lang=lang,View on GitHub (pinned to 1e661df964)
Solutions
- Exclude the three master tags from deletion: filter with lambda t: t not in (env.ref('account.account_tag_operating'), env.ref('account.account_tag_financing'), env.ref('account.account_tag_investing')).
- If they must be replaced, override/extend the report configuration instead of deleting the tags.
- In tests, use a guarded unlink or roll back the transaction rather than deleting master data.
Example fix
# before
env['account.account.tag'].search([...]).unlink() # hits master tag
# after
masters = [env.ref('account.' + x) for x in
('account_tag_operating', 'account_tag_financing', 'account_tag_investing')]
tags = env['account.account.tag'].search([...]).filtered(lambda t: t not in masters)
tags.unlink() Defensive patterns
Strategy: validation
Validate before calling
MASTER_TAG_XMLIDS = ('account.account_tag_operating',
'account.account_tag_financing',
'account.account_tag_investing')
master_ids = [env.ref(x, raise_if_not_found=False) for x in MASTER_TAG_XMLIDS]
master_ids = [t.id for t in master_ids if t]
deletable = tags.filtered(lambda t: t.id not in master_ids) Try / catch
from odoo.exceptions import UserError
try:
tags.unlink()
except UserError as e:
if 'chart of account definition' in str(e):
(tags - masters).unlink()
else:
raise Prevention
- Blacklist the three master tag XML IDs in any tag-cleanup job.
- Resolve tags by XML ID before deletion and skip protected ones.
- Don't wipe account.account.tag wholesale in tests; roll back the cursor instead.
When it happens
Trigger: Calling unlink() on an account.account.tag recordset that includes one of the three master tags resolved via env.ref('account.account_tag_operating'|'account_tag_financing'|'account_tag_investing').
Common situations: Bulk tag cleanup scripts that unlink all tags matching a pattern; attempting to 'reset' tags after a localization change by deleting everything; tests that wipe account.account.tag without filtering.
Related errors
- You cannot remove/deactivate the accounts "%s" which are set
- You cannot remove/deactivate the accounts "%s" which are set
- You can not delete a transaction from a valid statement.\nIf
- You can't delete a report that has variants.
- You cannot perform this action on an account that contains j
AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15).
Data as JSON: /api/errors/c199dc5f47378d53.
Report an issue: GitHub.