thingsboard/thingsboard · error · ThingsboardException
ITEM_NOT_FOUND
ITEM_NOT_FOUND
Error message
Alarm rule not found
What it means
Thrown by AlarmRuleController helper checkAlarmRule when the referenced CalculatedField exists but its type is not CalculatedFieldType.ALARM. 'Alarm rules' in this version are implemented as calculated fields of type ALARM; passing the ID of a regular (non-alarm) calculated field resolves the entity but fails the type check and reports ITEM_NOT_FOUND.
Source
Thrown at application/src/main/java/org/thingsboard/server/controller/AlarmRuleController.java:254
.orElse(null);
}
@ApiOperation(value = "Test alarm rule TBEL expression (testAlarmRuleScript)",
notes = TEST_SCRIPT_EXPRESSION + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@PostMapping("/alarm/rule/testScript")
public JsonNode testAlarmRuleScript(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Test alarm rule TBEL condition expression. The expression must return a boolean value.")
@RequestBody JsonNode inputParams) throws ThingsboardException {
checkParameter("expression", inputParams.has("expression") ? inputParams.get("expression").asText() : null);
return tbCalculatedFieldService.executeTestScript(getTenantId(), inputParams);
}
private CalculatedField checkAlarmRule(CalculatedFieldId calculatedFieldId) throws ThingsboardException {
CalculatedField calculatedField = tbCalculatedFieldService.findById(calculatedFieldId, getCurrentUser());
checkNotNull(calculatedField);
if (calculatedField.getType() != CalculatedFieldType.ALARM) {
throw new ThingsboardException("Alarm rule not found", ThingsboardErrorCode.ITEM_NOT_FOUND);
}
return calculatedField;
}
}
View on GitHub (pinned to 45c30e83fa)
Solutions
- Verify the ID with GET /api/calculatedField/{id} and check that type == 'ALARM'; if not, obtain the correct alarm rule ID from the alarm-rules listing endpoint.
- If the alarm rule was deleted, recreate it and update the referencing client/dashboard.
- Check for ID copy-paste errors between calculated fields and alarm rules in configs or imports.
Example fix
// before GET /api/alarm/rule/6f8f1a00-... // ID of a plain calculated field -> ITEM_NOT_FOUND "Alarm rule not found" // after // list alarm rules and use one whose type is ALARM: GET /api/alarm/rules?page=0&pageSize=10 GET /api/alarm/rule/<alarmRuleId-with-type-ALARM>
Defensive patterns
Strategy: validation
Validate before calling
// Resolve the ID through the calculated-field API and check the type first:
const cf = await tb.get(`/api/calculatedField/${calculatedFieldId}`);
if (cf.data.type !== 'ALARM') {
throw new Error(`${calculatedFieldId} is a '${cf.data.type}' calculated field, not an alarm rule`);
} Type guard
interface CalculatedFieldLike { id?: {id: string}; type?: string }
function isAlarmRule(cf: CalculatedFieldLike | null | undefined): cf is { id: {id: string}; type: 'ALARM' } {
return !!cf && cf.type === 'ALARM' && !!cf.id?.id;
} Try / catch
try { return await tb.get(`/api/alarm/rule/${id}`); }
catch (e) {
if (e.response?.status === 404 && /Alarm rule not found/.test(e.response.data.message)) {
return await listAlarmRules(); // re-resolve from the authoritative list
}
throw e;
} Prevention
- Keep alarm-rule IDs and calculated-field IDs in separate, clearly named config fields.
- After deleting a rule, immediately purge references in dashboards/scripts.
- Validate stored IDs against a fresh list after environment imports or migrations.
When it happens
Trigger: Calling an alarm-rule endpoint (e.g. GET /api/alarm/rule/{id} or testScript-related flows that go through checkAlarmRule) with the UUID of a calculated field created under /api/calculatedField whose type is SCRIPT or simple.
Common situations: UI state pointing at a stale ID after an alarm rule was deleted and its ID reused by a normal calculated field; scripts mixing IDs from the calculated-field API and the alarm-rule API; importing an entity where the rule reference was remapped incorrectly.
Related errors
- ITEM_NOT_FOUND
- Unsupported referenced entity type: '{}'.
- Zone group configuration is missing for the: {}
- Invalid perimeter data source for zone with id: {}. Perimete
- Unsupported argument type: {} detected for argument: {}. Onl
AI-assisted analysis of thingsboard/thingsboard@45c30e83fa (2026-08-14).
Data as JSON: /api/errors/d83c0f5ab2f101df.
Report an issue: GitHub.