Diagnostics
The Diagnostics page runs a battery of read-only health checks across the database and live system state, then surfaces orphans, duplicates, broken references, stale data, and configuration smells. It's the first place to look when something feels wrong but no error is being thrown — and the right tool for periodic hygiene sweeps before backups, upgrades, or handover.
What it checks
Each check is a small read-only routine that returns 0..N issues. Checks never mutate state — they're safe to run anytime, including in production.
| Category | Examples |
|---|---|
| Orphan References | macro steps (or a step's device/zone/macro target) pointing at a deleted record; AV sources or AV zones whose backing device or zone was removed; UI controls, page widgets, and zone mappings bound to deleted zones or widgets; schedules and attribute triggers pointing at a missing macro; sub-devices whose controller device was deleted; zones whose subsystem was removed |
| Duplicates | two devices configured with the same IP; multiple zones sharing a name within a subsystem; macro names that collide |
| Empty / Unused | enabled macros with no enabled steps; AV zones with no sources; UI pages with no widgets; widgets defined but never placed |
| Naming Issues | entity names that violate the lowercase_with_underscores convention |
| Connectivity | enabled devices reporting disconnected; enabled devices that look connected but haven't pushed any attribute update in 24h+ (activity on a device's zones counts — drivers like BACnet/Modbus report onto zone attributes rather than device attributes); dynamic attributes (state/level/temperature/etc.) that haven't changed in 48h+ |
| Config Smells | sensitive-looking attributes (password, api_key, etc.) stored in plaintext — a row whose Secure switch is on counts as protected, whatever its stored form looks like; disabled steps inside enabled macros; float attributes recording history that no deadband can reach |
| Security | roles with no users assigned; admin accounts inactive for 90+ days |
| Integrity | recursive macro execution loops (run_macro / for_each cycles) — surfaced with the actual cycle path |
| Performance | attribute_history table size warnings (>500K rows = moderate, >1M = large, >5M = very large); attributes flooding attribute_history — see below; host disk and memory headroom running short |
Attributes flooding attribute history
attribute_history is the highest-volume table in the system, and a single fast-polling analog attribute can account for most of it. Two checks watch for that, and they answer different questions.
"Attributes flooding attribute_history" (Performance) names the attributes filling the table right now. Row count alone can't distinguish a genuinely eventful attribute from one nothing is filtering, so the check uses two signals together — an attribute is flagged only when it writes more than 60 rows/hour and the History Deadband is rejecting under 5% of the samples it offers. A doorbell that writes four rows a day is never flagged; neither is a busy meter whose deadband is doing its job. Findings are grouped by attribute name, so fifty breaker circuits writing the same attribute are one issue rather than fifty.
The counters are kept in memory as attributes are written, so the check costs nothing to run — but it needs at least five minutes of uptime before it will report, since a shorter window can't be extrapolated to an hourly rate honestly. A summary line is also written to the log once per hour whenever anything is flooding.
"History attributes the deadband cannot reach" (Config Smells) is the static half. The deadband only applies to float attributes that have an attribute registry entry with history enabled. An attribute row with history set directly but no matching registry entry is waved straight through — every poll writes a row, no matter what history_deadband_percent says. This check finds those, and it's worth acting on even when the attribute isn't currently flooding, because nothing is holding it back if the poll rate ever increases.
Both findings are acted on in the same place: Top Attribute History Writers on the Data Retention page gives the per-attribute breakdown, including which individual entities are worst, and a Tune button per attribute that sets its deadband or stops it recording — including for the attributes the global deadband cannot reach.
"Host resources are running short" (Performance) reports disk and memory headroom on the machine GEM runs on, from a sampler that reads disk, memory and CPU every five minutes. It reports at a deliberately lower bar than the alarms fired from the same samples — disk from 80%, memory from 85%, where nobody is being paged — because 80% full is not worth waking anyone and is exactly what you want to see on a page you opened on purpose. When the database size is known it is named beside the disk figure, since history is nearly always what filled it.
The raw numbers are also kept as system attributes (disk_used_percent, disk_free_gb, memory_used_percent, cpu_load_percent, database_size_mb), so they can be charted, read from a macro, or given conditions of your own.
Running the checks
- Navigate to Insights → Diagnostics (Open Diagnostics)
- The page runs every check on load; results appear within a couple of seconds for most installs
- Click Re-run to refresh after fixing something
Diagnostics requires an elevated session — the sweep reads administrator account details and reports credential-bearing attributes, so the underlying function is admin-only. One sweep runs at a time system-wide: a Re-run clicked while another admin's sweep is still in flight joins the running one and returns the same result, rather than starting a second full-table scan on the controller.
When every check passes, the card list is replaced by a green "All N checks passed. The system looks healthy." banner — a clean run is the expected result on a well-maintained system.
The summary header shows four tiles: Checks (how many checks ran) and Errors / Warnings / Info. The three severity tiles count affected items, not checks — one check that flags twelve zones adds 12 to its severity tile, so these numbers track the size of the cleanup, not the number of findings.
Filtering and triage
- Search — full-text filter across issue titles, descriptions, and the label and details of every affected item. Useful when you know an entity name and want to find every check that flagged it.
- Severity filter — narrow to errors-only, warnings-only, or info-only.
- Category filter — narrow to one category (e.g. only Orphan References).
Issues are sorted errors → warnings → info, and within severity by item count descending — so the most urgent thing to fix is always at the top.
Issue cards
Each issue card shows:
- Severity badge —
error/warning/info - Title — what the check found
- Count — how many entities are affected
- Category — one of the categories above
- Description — what the check is looking for
- Fix — the recommended remediation
- Affected items — drill-down list: each row shows a label, its details, and an Open › button that jumps straight to the relevant admin page. On the standard list screens (Devices, Zones, Macros, AV Zones, Triggers, Users, Roles, and the like) it opens pre-filtered to the offending row, and when the filter matches exactly one record that record's editor opens with it. The filter is resolved against the whole table, so the row is found even when it would otherwise sit several pages deep — and it works on grids that don't show an ID column of their own, such as AV Zones. A Clear button appears in the grid toolbar to drop the filter and see the whole table again. Where a page carries more than one grid (for example Triggers, which also lists command → macro bindings), only the page's main grid takes the filter. A handful of screens you browse differently — AV Sources, UI Pages, and Attributes, which you open by system target — land you on the right screen to find the record yourself.
Click the card header (or the Hide items / Show N items toggle at the foot of each card) to collapse the affected-item list when you want a higher-level view.
The Open › button on each item is the fastest way to fix an issue — instead of browsing back to e.g. Macros and searching for the offender, click straight through to the row that needs attention.
When to run
- Before a backup — a clean diagnostics run = a clean backup. Catches dangling references that would silently bloat the snapshot.
- After a large migration or import — verify orphan references didn't get introduced by partial imports.
- Quarterly hygiene — admin accounts inactive for 90+ days, plaintext secrets, large
attribute_historytable. - When something feels off — silent device, missing alert, scene that does nothing. Diagnostics often surfaces the cause without needing to dig through logs.
Explain & Fix with AI
The Explain & Fix with AI button in the header opens the AI assistant with a narrated audit: the assistant re-runs the same check battery itself (so its view is always current), walks the findings worst-first in plain language, and proposes concrete next steps. Where one of its tools can make the repair (rebinding a stale reference, correcting an attribute), it offers to do it — every change still goes through the normal confirmation gate — and for anything else it points you at the right admin page. You can also ask follow-ups ("only the security findings", "why does macro 12 keep showing up here?").
What it does NOT do
- No mutations. Diagnostics never deletes orphans, fixes references, or changes attributes. Each fix has to be made deliberately on the appropriate admin page — or explicitly approved through the AI assistant's confirmation prompt — so you don't lose work to a bulk auto-clean.
- Not a replacement for monitoring. Stale-attribute and disconnected-device checks are useful for hygiene but won't page you. Use Monitoring for active alerting.
- Not a backup audit. For verifying backup integrity, see Backup & Restore.
Related Documentation
- Monitoring — active alerting on device health
- Device Health — long-form connectivity history
- Data Retention — control attribute_history growth flagged by the performance check
- Backup & Restore — snapshot the database
- Macros — fix recursion cycles flagged by the integrity check
- Import / Export — share known-good configurations between installations