{"record":{"id":"bbb9336887c3bbac","repo":"odoo/odoo","slug":"line-s-defines-itself-as-its-parent","errorCode":null,"errorMessage":"Line \"%s\" defines itself as its parent.","messagePattern":"Line \"(.+?)\" defines itself as its parent\\.","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"addons/account/models/account_report.py","lineNumber":447,"sourceCode":"            try:\n                report_line._validate_groupby()\n            except UserError:\n                report_line.user_groupby = report_line.groupby\n\n    @api.constrains('parent_id')\n    def _validate_groupby_no_child(self):\n        for report_line in self:\n            if report_line.parent_id.groupby or report_line.parent_id.user_groupby:\n                raise ValidationError(_(\"A line cannot have both children and a groupby value (line '%s').\", report_line.parent_id.name))\n\n    @api.constrains('groupby', 'user_groupby')\n    def _validate_groupby(self):\n        self.expression_ids._validate_engine()\n\n    @api.constrains('parent_id')\n    def _check_parent_line(self):\n        for line in self.filtered(lambda x: x.parent_id == x):\n            raise ValidationError(_('Line \"%s\" defines itself as its parent.', line.name))\n\n    def _copy_hierarchy(self, copied_report, parent=None, code_mapping=None):\n        ''' Copy the whole hierarchy from this line by copying each line children recursively and adapting the\n        formulas with the new copied codes.\n\n        :param copied_report: The copy of the report.\n        :param parent: The parent line in the hierarchy (a copy of the original parent line).\n        :param code_mapping: A dictionary keeping track of mapping old_code -> new_code\n        '''\n        self.ensure_one()\n\n        copied_line = self.copy({\n            'report_id': copied_report.id,\n            'parent_id': parent and parent.id,\n            'code': self._get_copied_code(),\n        })\n\n        # Keep track of old_code -> new_code in a mutable dict","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/odoo/odoo/blob/1e661df964b1b264c9cef3ab28430d4785be3fda/addons/account/models/account_report.py#L429-L465","documentation":"Raised by `_check_parent_line` on `account.report.line`: a line whose `parent_id` equals itself is rejected (`x.parent_id == x`). Self-parenting would create a cycle in the line tree, which the report renderer cannot traverse.","triggerScenarios":"`create()`/`write()` with `parent_id` set to the same record as the line itself — e.g. after copying a line and remapping parent ids with a buggy mapping dict that maps the line to itself, or assigning `parent_id` from a variable that accidentally holds the line.","commonSituations":"Copy/duplicate routines that remap `parent_id` via an old-id-to-new-id dict and hit a self-reference when the mapping is built incorrectly; import scripts that resolve parent codes to the same line; drag-and-drop re-parenting bugs in custom UIs.","solutions":["Set `parent_id` to a *different* line, or to `False` for a root line","In copy code, skip the self-reference: map `parent_id` only when `new_parent != copied_line`","Validate imports up front: reject rows whose parent code equals their own code"],"exampleFix":"# before\nnew_line = line.copy({'parent_id': new_line_id_map[line.id]})  # map may contain line.id -> its own new id\n\n# after\nnew_line = line.copy({'parent_id': new_line_id_map.get(line.parent_id.id, False)})","handlingStrategy":"validation","validationCode":"if vals.get('parent_id') and vals['parent_id'] == line.id:\n    vals['parent_id'] = False  # or raise\nline.write(vals)","typeGuard":null,"tryCatchPattern":"from odoo.exceptions import ValidationError\ntry:\n    line.write({'parent_id': parent_id})\nexcept ValidationError:\n    line.write({'parent_id': False})","preventionTips":["In copy/remap code, build the old->new parent map from `line.parent_id`, never from `line.id`","Validate imported rows: parent code must differ from the line's own code","Unit-test hierarchy builders for cycles"],"tags":["odoo","accounting","account-report","hierarchy","cycle","constraint"],"backgroundTag":null,"analyzedSha":"1e661df964b1b264c9cef3ab28430d4785be3fda","analyzedAt":"2026-08-15T05:22:16.142Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}