Skip to content

spp_hide_menus_base: hide_menus() runs env.ref from _register_hook with no database-error guard, so a poisoned cursor aborts every registry load #526

Description

@gonzalesedwin1123

Found while fixing #383 (PR #525).

spp_hide_menus_base/models/ir_module_module.py runs hide_menus() from _register_hook, i.e. at the end of every registry load (startup, install, upgrade, and every worker/registry reload). Since b28e26e (2026-06-04). Inside the loop it calls self.search([]), self.env.ref(...) → ir.model.data._xmlid_lookup, spp.hide.menu search/create and hide_menu() / _reapply_hide(), with only a ValueError guard around the lookup. Any psycopg2.Error propagates out of _register_hook and aborts the registry load.

This is the shape of the 2026-07-30 preprod incident that OpenSPP/odoo-job-worker#22 describes: a UniqueViolation elsewhere poisoned the cursor, and env.ref → _xmlid_lookup in an ir.module.module hook then raised InFailedSqlTransaction "during registry load on each restart", killing the worker thread until the database was quarantined. #383 attributed that frame to spp_base_common's menu-icon hook, but on Odoo 19 that hook only runs from ir.module.module.next(), which is called solely by the install/upgrade buttons after cr.reset() and never on registry load. The _register_hook here is the one that actually executes on the worker's Registry(db_name) path, and it predates the incident. (The original traceback was not preserved anywhere we could find, so this is inference from the code paths, not a confirmed frame.)

Proposed direction

Same treatment as #383 / PR #525, scoped to this module:

  • run the hide_menus() pass inside with self.env.cr.savepoint(): and catch psycopg2.Error (not just DatabaseError: InterfaceError is a sibling class), log at WARNING with exc_info=True, and skip. Hiding menus is important but must be best-effort at registry load: a menu left visible is recoverable, an aborted registry load is an outage (cf. spp.hide.menu: a duplicate menu_id row aborts the registry load (ValueError: Expected singleton in _register_hook) #408).
  • raise_if_not_found=False on the env.ref instead of catching ValueError.
  • Regression tests: a SQL failure raised inside the lookup, and a cursor already aborted before _register_hook runs, both asserting the hook does not raise and (for the first) that the transaction is still usable. Note for the test author: Odoo's assertRaises wraps its body in a savepoint and rolls it back, so it cannot be used to poison the cursor; use contextlib.suppress and assert cr._cnx.get_transaction_status() == TRANSACTION_STATUS_INERROR as the precondition.
  • Bump spp_hide_menus_base (currently 19.0.2.1.0) + HISTORY fragment.

Related: #410 (re-snapshot degradation on the same hide_menu() path), #408 (previous _register_hook outage).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions