Troubleshooting
What goes wrong with Database Health Monitor, how to recognise it, and what to do.
Nothing on the dashboard ever updates
The scheduled action is not running. Settings → Technical → Scheduled Actions → Database Health: run checks. Check it is active and look at its next-run time.
If Odoo has deactivated it after repeated failures, the reason is in the server log. Note that a probe failing does not do this — probe failures are caught and stored as unknown readings precisely so the cron survives them.
A check reads "unknown" with an error in its detail
The probe guard working. It caught the failure, rolled back its savepoint and stored the error rather than letting it escape and take the whole run with it.
Read the error text. Common ones:
- statement timeout — the probe hit its five-second ceiling. On a very large database the largest-table probe can do this; raise the window or accept it.
- permission denied — the database user cannot read a system view.
- relation does not exist — a source points at a model that is not installed.
A check reads "unknown" with no error
Nothing has reported. That is one of:
- an integration check with no source registered — register one;
- an agent check with no agent reporting — see below.
This is the designed state, not a fault.
The agent posts and nothing changes
In order:
- Is Accept agent reports on? It is off by default. Without it the route answers as if it does not exist.
- Is the token in the header? Authorization: Bearer <token>. It is not accepted in a query string, deliberately.
- Is the fact code one of the six? disk_free_percent, disk_free_bytes, backup_age_hours, backup_size_bytes, filestore_bytes, load_average. Anything else is rejected rather than stored under a name nobody will look for.
- IP allowlist. If set, the agent's address has to be in it.
- Rate limit. A chatty agent can hit it.
The endpoint records last request at and last source IP. If those are updating, the request is arriving and the problem is the payload.
The status endpoint returns 503 and everything looks fine
503 covers critical and unknown. A check nobody can answer is not a healthy check, so a single unknown is enough.
Open the dashboard and look for unknowns rather than only for reds.
The status endpoint returns 404
Expose status is off, or the endpoint record is archived. Both make the route behave as though it does not exist, which is the right answer to give an unauthenticated caller.
Alerts are not arriving
Both switches have to be on: the company master switch and the check's own Alert on. Then check Odoo's own mail queue — this module hands the message to Odoo and a stuck outgoing mail server stops it there.
Worth noting the module monitors that too: Mail delivery failures and Oldest unsent message are two of the thirteen checks.
The same alert keeps arriving
The cooldown is too short for how you work. Raise Alert cooldown (hours) on that check.
Be aware that raising it does not delay an escalation: a move from warning to critical is sent immediately regardless. The cooldown suppresses repetition, not news.
An alert stopped arriving but the problem is still there
Expected — the condition is unresolved and the cooldown is suppressing repeats. The dashboard still shows it. Acknowledge clears the cooldown if you want the next one sooner.
Acknowledging did not turn it green
By design. Acknowledge affects the cooldown, never the severity. Seeing a problem is not fixing one.
History is empty or short
Retention (days) on that check, and the Database Health: prune history job which enforces it. Raise the retention if you need a longer view; the readings are small rows.
Server errors always reads zero
It counts ir_logging rows, which depend on the server's log_db setting. With log_db off nothing is written there and zero means "not recorded". The reading says so in its detail.
A source's domain is rejected
It must be a plain Odoo domain — [('state', '=', 'error')]. It is read as data and never evaluated as Python, so an expression will not work here. That is a deliberate limit: a configuration screen that evaluates Python is a remote-code-execution hole.