Skip to content

OD603 unknown-rpc-model

An ORM call from JS names a model no indexed module defines.

Category Severity Series Needs the index
Correctness Error all yes

What it reports

A call of the orm service, such as this.orm.call(), searchRead(), read() or write(), whose first argument is a literal model name that no indexed module defines, or that only a module missing from depends defines. The service is recognised as orm, something.orm, and either one through .silent or .cache(...). A module that Odoo always installs with base, such as web, counts as in depends.

Why it matters

The server looks the model up when the request arrives and answers with an error the user sees as a dialog, every time the call runs. A model of a module that is not in depends exists only where that module happens to be installed. The usual cause is a typo, or a model renamed or removed upstream between series.

The rule skips a model built at runtime, such as this.props.resModel. In a module that builds model names in Python at runtime, it skips any model no indexed module defines, and a model of a module missing from depends when the module may build that model itself. That is a name that fits an expression code outside tests/ builds _name from, where an expression that shows no literal start fits every name, or the name a class may take in a module of unknown series, as Series describes. Like OD601, it reads only scripts a bundle loads as ES modules.

The rule stays silent on a model that a dependency that is not indexed, such as an Enterprise module, could load. A model the module defines whole is in scope, so the rule never reports one. Add the checkout of the dependency that is not indexed to --addons-path to check the other models.

Example

static/src/js/company_list.js
const companies = await this.orm.searchRead("res.partners", [["is_company", "=", true]], ["name"]);

The model is res.partner.

static/src/js/company_list.js
const companies = await this.orm.searchRead("res.partner", [["is_company", "=", true]], ["name"]);

Suppressing

// odooscan: ignore[OD603]
const companies = await this.orm.searchRead("res.partners", [["is_company", "=", true]], ["name"]);

See suppressing a finding.