{"record":{"id":"c199dc5f47378d53","repo":"odoo/odoo","slug":"you-cannot-delete-this-account-tag-s-it-is-use","errorCode":null,"errorMessage":"You cannot delete this account tag (%s), it is used on the chart of account definition.","messagePattern":"You cannot delete this account tag \\((.+?)\\), it is used on the chart of account definition\\.","errorType":"exception","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"addons/account/models/account_account_tag.py","lineNumber":120,"sourceCode":"        return self.env['account.report.expression'].search(Domain('engine', '=', 'tax_tags') & Domain.OR(\n            (\n                Domain('report_line_id.report_id.country_id', '=', record.country_id.id)\n                & Domain('formula', 'in', (record.name, '-' + record.name))\n            )\n            for record in self\n        ))\n\n    @api.ondelete(at_uninstall=False)\n    def _unlink_except_master_tags(self):\n        master_xmlids = [\n            \"account_tag_operating\",\n            \"account_tag_financing\",\n            \"account_tag_investing\",\n        ]\n        for master_xmlid in master_xmlids:\n            master_tag = self.env.ref(f\"account.{master_xmlid}\", raise_if_not_found=False)\n            if master_tag and master_tag in self:\n                raise UserError(_(\"You cannot delete this account tag (%s), it is used on the chart of account definition.\", master_tag.name))\n\n    def _translate_tax_tags(self, langs=None, tag_ids=None):\n        \"\"\"Translate tax tags having the same name as report lines.\"\"\"\n        langs = langs or (code for code, _name in self.env['res.lang'].get_installed() if code != 'en_US')\n        for lang in langs:\n            self.env.cr.execute(SQL(\n                \"\"\"\n                UPDATE account_account_tag tag\n                   SET name = tag.name || jsonb_build_object(%(lang)s, substring(tag.name->>'en_US' FOR 1) || (report_line.name->>%(lang)s))\n                  FROM account_report_line report_line\n                  JOIN account_report report ON report.id = report_line.report_id\n                 WHERE tag.applicability = 'taxes'\n                   AND tag.country_id = report.country_id\n                   AND tag.name->>'en_US' = substring(tag.name->>'en_US' FOR 1) || (report_line.name->>'en_US')\n                   AND tag.name->>%(lang)s != substring(tag.name->>'en_US' FOR 1) || (report_line.name->>%(lang)s)\n                   %(and_tag_ids)s\n                \"\"\",\n                lang=lang,","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/odoo/odoo/blob/1e661df964b1b264c9cef3ab28430d4785be3fda/addons/account/models/account_account_tag.py#L102-L138","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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."],"exampleFix":"# before\nenv['account.account.tag'].search([...]).unlink()  # hits master tag\n\n# after\nmasters = [env.ref('account.' + x) for x in\n    ('account_tag_operating', 'account_tag_financing', 'account_tag_investing')]\ntags = env['account.account.tag'].search([...]).filtered(lambda t: t not in masters)\ntags.unlink()","handlingStrategy":"validation","validationCode":"MASTER_TAG_XMLIDS = ('account.account_tag_operating',\n                        'account.account_tag_financing',\n                        'account.account_tag_investing')\nmaster_ids = [env.ref(x, raise_if_not_found=False) for x in MASTER_TAG_XMLIDS]\nmaster_ids = [t.id for t in master_ids if t]\ndeletable = tags.filtered(lambda t: t.id not in master_ids)","typeGuard":null,"tryCatchPattern":"from odoo.exceptions import UserError\ntry:\n    tags.unlink()\nexcept UserError as e:\n    if 'chart of account definition' in str(e):\n        (tags - masters).unlink()\n    else:\n        raise","preventionTips":["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."],"tags":["odoo","accounting","delete-guard","account-tag","ondelete"],"backgroundTag":null,"analyzedSha":"1e661df964b1b264c9cef3ab28430d4785be3fda","analyzedAt":"2026-08-15T05:22:16.142Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}