Skip to content

OD201 unknown-model

The model is not defined by any indexed module.

Category Severity Series Needs the index
Correctness Error all yes

What it reports

A model name that no module on the addons path defines, where Odoo needs the model to exist: a parent in _inherit, the comodel of a Many2one, One2many or Many2many, the model of a view, the model of a <record>, the model a data CSV is named after, and the res_model of a window action, as a <record> or an <act_window> gives it literally. Those places are all it reads. A <function> on an unknown model stops its file from loading too, but neither this rule, OD202 nor OD314 reports it. A model that another indexed module defines, but that module is missing from depends, is OD202 instead. A demo file is read like a data file.

Why it matters

Odoo builds a model on top of every parent in _inherit and raises TypeError when one is not in the registry, so the module cannot be installed and a database that already has it fails to start. A view or a window action whose model does not exist fails validation when its file loads, and a <record> of an unknown model, or a data CSV named after one, stops its file from loading. That aborts the install when the file is a data file, or a demo file before saas~11.5. From saas~11.5 Odoo logs a warning instead and installs the module without its demo data. A relational field on an unknown model stops the install from saas~18.2. Before that Odoo logs a warning and points the field at a placeholder model, so it never holds a record.

Most findings are typos or models renamed between versions. A model from a module that is not on the addons path, such as an Enterprise module, is reported too: add that module's directory to the addons path rather than suppressing the finding. The model of a <record> and the model a data CSV is named after get no finding in a module whose dependencies include one that is not indexed, because that dependency may define the model. The other places are still reported. A model that a view, a window action, a <record> or a data CSV names gets no finding when a module in scope loads an unread data file, which may define it. A module whose classes build _name from an expression gets no finding, because the models it defines cannot be listed before it runs.

Example

models/sale_order_line.py
class SaleOrderLine(models.Model):
    _inherit = "sale.order.lines"

    partner_tag_ids = fields.Many2many("res.partner.categories")

The model is sale.order.line, and partner tags are res.partner.category.

models/sale_order_line.py
class SaleOrderLine(models.Model):
    _inherit = "sale.order.line"

    partner_tag_ids = fields.Many2many("res.partner.category")

Suppressing

partner_tag_ids = fields.Many2many("x_partner_tag")  # odooscan: ignore[OD201]

For a data CSV, where a comment would break the file, pass --ignore OD201 or add it to ignore in the configuration file.

See suppressing a finding.