odoo/odoo · error · UserError

Cannot get aggregation details from a line not using 'aggreg

Error message

Cannot get aggregation details from a line not using 'aggregation' engine

What it means

Raised by `_get_aggregation_terms_details()` on `account.report.expression`: this helper parses aggregation formulas by splitting them into `line_code.total` terms, so every expression in `self` must have `engine == 'aggregation'`. Passing any expression with a different engine (`domain`, `tax_tags`, `account_codes`, `external`) is a programming error.

Source

Thrown at addons/account/models/account_report.py:870

            if domains:
                sub_expressions |= self.env['account.report.expression'].search(Domain.OR(domains))

            to_expand = sub_expressions.filtered(lambda x: x.engine == 'aggregation' and x not in result)
            result |= sub_expressions

        return result

    def _get_aggregation_terms_details(self):
        """ Computes the details of each aggregation expression in self, and returns them in the form of a single dict aggregating all the results.

        Example of aggregation details:
        formula 'A.balance + B.balance + A.other'
        will return: {'A': {'balance', 'other'}, 'B': {'balance'}}
        """
        totals_by_code = defaultdict(set)
        for expression in self:
            if expression.engine != 'aggregation':
                raise UserError(_("Cannot get aggregation details from a line not using 'aggregation' engine"))

            expression_terms = re.split('[-+/*]', re.sub(r'[\s()]', '', expression.formula))
            for term in expression_terms:
                if term and not re.match(r'^([0-9]*[.])?[0-9]*$', term): # term might be empty if the formula contains a negative term
                    line_code, total_name = term.split('.')
                    totals_by_code[line_code].add(total_name)

            if expression.subformula:
                if_other_expr_match = re.match(r'if_other_expr_(above|below)\((?P<line_code>.+)[.](?P<expr_label>.+),.+\)', expression.subformula)
                if if_other_expr_match:
                    totals_by_code[if_other_expr_match['line_code']].add(if_other_expr_match['expr_label'])

        return totals_by_code

    def _get_matching_tags(self):
        """ Returns all the signed account.account.tags records whose name matches any of the formulas of the tax_tags expressions contained in self.
        """
        tag_expressions = self.filtered(lambda x: x.engine == 'tax_tags')

View on GitHub (pinned to 1e661df964)

Solutions

  1. Filter first: `expressions.filtered(lambda e: e.engine == 'aggregation')._get_aggregation_terms_details()`
  2. If a term is genuinely computed another way, move it to an `aggregation`-engine expression or stop feeding it to this helper

Example fix

# before
details = line.expression_ids._get_aggregation_terms_details()  # may contain non-aggregation expressions

# after
details = line.expression_ids.filtered(lambda e: e.engine == 'aggregation')._get_aggregation_terms_details()
Defensive patterns

Strategy: type-guard

Validate before calling

agg_exprs = expressions.filtered(lambda e: e.engine == 'aggregation')
details = agg_exprs._get_aggregation_terms_details()

Type guard

def is_aggregation_expression(expr) -> bool:
    """_get_aggregation_terms_details only accepts aggregation-engine expressions."""
    return expr.engine == 'aggregation'

Try / catch

from odoo.exceptions import UserError
try:
    details = exprs._get_aggregation_terms_details()
except UserError:
    details = exprs.filtered(lambda e: e.engine == 'aggregation')._get_aggregation_terms_details()

Prevention

When it happens

Trigger: Calling `expression._get_aggregation_terms_details()` where `expression` (or any record in the recordset) has an engine other than `'aggregation'`. In framework code this is called on `to_expand` candidates; in custom code it is usually called on an unfiltered expression recordset.

Common situations: Custom report tooling iterating over all expressions of a line/report without filtering by engine; changing an expression's engine after formulas were set; subclass code reusing the helper for validation.

Related errors


AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15). Data as JSON: /api/errors/d5b94ae0a7ebd615. Report an issue: GitHub.