Skip to main content
Work top-down when an alarm misbehaves: definition saved → definition active → rule evaluates → instance opens → notification delivered. Set these for the copyable commands:
Errors use the envelope {"ok": 0, "message": "…", "detail": "…"}. The message field carries the reason quoted in this guide.

Quick diagnostic flow

Symptom index


Rejected definitions

Create (POST …/alarm-definitions) and update (PATCH …/alarm-definitions/{alarm_def_id}) check the definition before saving it. An update is checked as the merged result of your change and the stored definition. Missing key, name, or condition_cel on create also returns 400.

Query budget rejections

Symptoms: 400 on create or update with one of:
  • query_spec.sql must bound event_ts with a relative window (e.g. event_ts >= now() - INTERVAL 4 HOUR); an unbounded scan stalls the shared evaluator
  • query_spec.sql must not pin an absolute time bound; use a relative window (e.g. event_ts >= now() - INTERVAL 4 HOUR)
  • query_spec.sql scans a … window, over the 24h0m0s cap; narrow the relative window
Cause: Every scheduled query — threshold rules, and event rules that carry SQL — must scan a bounded, recent slice of data. The query must:
  1. Filter event_ts with a window relative to now().
  2. Use a window of 24 hours or less.
  3. Contain no absolute time floor — no date literal such as '2026-01-01' and no toDateTime(…), parseDateTime…(…), or fromUnixTimestamp…(…) call.
Fix: Rewrite the filter in one of the accepted forms:
In the Console, the Test panel shows not bounded and does not run the query until the SQL has a relative event_ts window.

Query rejected by the gateway

After the budget check, the platform plans your SQL against the dataspace without running it. An update only re-validates the SQL when you change query_spec or kind. Changing other fields works even while validation is unavailable.

Duplicate key

Symptom: 409 with alarm definition key already exists in project. Fix: Each definition key must be unique in the project. Choose a new key, or update the existing definition instead.

PATCH did not change a field

Symptoms:
  • 400 with _keys is required
  • 200 response, but a field you sent kept its old value
Cause: PATCH on definitions, silences, and inhibitions only applies the fields named in _keys. Fields in the body but not in _keys are ignored. Fix:

Rule quarantined

Symptoms:
  • A threshold or event rule shows Deactivated in Alarms → Definitions, but nobody deactivated it
  • GET …/alarm-definitions/{alarm_def_id} returns "is_active": false
Cause: Each scheduled evaluation has a time budget equal to the rule’s evaluation interval, with a floor of 5 seconds and a cap of 60 seconds. An evaluation counts as an overrun when it takes longer than that budget, times out, or is turned away because the query service is overloaded. After 3 consecutive overruns the platform deactivates the rule so it cannot slow down evaluation for everyone else. Fix:
  1. Make the query cheaper: narrow the event_ts window, filter earlier, and aggregate less.
  2. Raise eval_interval_seconds if the rule does not need to run that often.
  3. Reactivate the rule. Reactivating clears the quarantine and resets the overrun count.
If the query is still too slow, the rule is quarantined again after three more overruns.

Rule never fires

Check these in order.
A CEL expression that does not compile, or does not return a bool (for example event.temperature + 1), is still saved. It then fails on every evaluation and the rule never fires. Check expressions carefully before saving.

Staleness rule and non-MQTT devices

Symptom: A staleness (device-offline) rule never fires for LoRaWAN, HTTP, or OPC UA devices. Cause: “Offline” means the MQTT broker recorded a disconnect. Staleness rules only cover the project’s enabled MQTT devices. Devices that never hold a broker connection are never “offline” in this sense. Fix: Use a threshold rule that alarms when telemetry stops arriving, based on max(event_ts) in the device’s dataspace. For example, compare max(event_ts) per device against now() inside a window of 24 hours or less. Timing to expect:
  • Offline devices are checked once a minute, so firing lands up to about a minute after staleness_window_seconds elapses. eval_interval_seconds has no effect on staleness rules.
  • A reconnect resolves the device’s offline alarms immediately, without waiting for the next check.

Never-connected devices

Symptom: A device-offline alarm opens for a device that was created but never deployed. Cause: A device that has never connected counts as offline since the moment it was created. Fix: Disable devices that are not deployed yet, or connect them once. Use a silence if you only need to stop notifications while you roll out.

Alarm does not go away

→ States and timing: Alarms overview and Kinds and conditions

No notification

Symptom: The instance appears on the Board, but no message arrives. Silences and inhibitions suppress notifications only. The alarm instance still opens, shows on the Board, and can be acknowledged.
Changes to silences and inhibitions can take up to about 15 seconds to apply.
List the project’s subscriptions:
→ Full setup: Notifications and Silences and shelving

Shelve rejected


Console Test shows not available

Symptom: In the definition editor, Test shows the Condition check as not available. Cause: The platform cannot dry-run the CEL condition yet. The query check still runs your SQL against the dataspace. Fix: Confirm the query returns the rows you expect, save the rule, and watch the Board for the result. Event rules without a query have no dry-run either — write a matching row to the dataspace instead.

Permissions and rate limits

Per-second limits for alarm routes:

Still stuck?