thingsboard/thingsboard · error · ResponseStatusException
RpcStatus: DELETED
Error message
RpcStatus: DELETED
What it means
listRuleEngineRequestssByDevice (RPC list endpoint in RpcV2Controller) rejects RpcStatus.DELETED as a filter value with ResponseStatusException(400, 'RpcStatus: DELETED'). DELETED is a tombstone status used internally for removed persistent RPCs; it is not a queryable list status alongside QUEUED/SENT/DELIVERED/SUCCESSFUL/TIMEOUT/EXPIRED/FAILED.
Source
Thrown at application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java:190
@ResponseBody
public DeferredResult<ResponseEntity> getPersistedRpcByDevice(
@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(DEVICE_ID) String strDeviceId,
@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@Parameter(description = "Status of the RPC", schema = @Schema(allowableValues = {"QUEUED", "SENT", "DELIVERED", "SUCCESSFUL", "TIMEOUT", "EXPIRED", "FAILED"}))
@RequestParam(required = false) RpcStatus rpcStatus,
@Parameter(description = RPC_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "expirationTime", "request", "response"}))
@RequestParam(required = false) String sortProperty,
@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"}))
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("DeviceId", strDeviceId);
if (rpcStatus != null && rpcStatus.equals(RpcStatus.DELETED)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "RpcStatus: DELETED");
}
TenantId tenantId = getCurrentUser().getTenantId();
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
DeviceId deviceId = new DeviceId(UUID.fromString(strDeviceId));
final DeferredResult<ResponseEntity> response = new DeferredResult<>();
accessValidator.validate(getCurrentUser(), Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<>() {
@Override
public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
PageData<Rpc> rpcCalls;
if (rpcStatus != null) {
rpcCalls = rpcService.findAllByDeviceIdAndStatus(tenantId, deviceId, rpcStatus, pageLink);
} else {
rpcCalls = rpcService.findAllByDeviceId(tenantId, deviceId, pageLink);
}
response.setResult(new ResponseEntity<>(rpcCalls, HttpStatus.OK));
}View on GitHub (pinned to 45c30e83fa)
Solutions
- Remove DELETED from the status filter options; only send QUEUED, SENT, DELIVERED, SUCCESSFUL, TIMEOUT, EXPIRED or FAILED
- To find removed RPCs, omit the filter and inspect records whose status is DELETED in the page items instead of filtering server-side
- Fix enum-driven UI to blacklist DELETED for list queries
Example fix
// before
const url = `/api/rpc/${deviceId}?rpcStatus=DELETED&page=0&pageSize=10`;
// after
const url = `/api/rpc/${deviceId}?page=0&pageSize=100`;
const deleted = (await get(url)).data.filter(r => r.status === 'DELETED'); Defensive patterns
Strategy: validation
Validate before calling
const LISTABLE = ['QUEUED','SENT','DELIVERED','SUCCESSFUL','TIMEOUT','EXPIRED','FAILED'];
if (rpcStatus && !LISTABLE.includes(rpcStatus)) throw new Error('DELETED is not a list filter'); Type guard
function isListableRpcStatus(s) { return ['QUEUED','SENT','DELIVERED','SUCCESSFUL','TIMEOUT','EXPIRED','FAILED'].includes(s); } Try / catch
catch (e) { if (e.status === 400 && /RpcStatus: DELETED/.test(e.message)) { refetchWithoutStatusFilter(); } else throw e; } Prevention
- Build status dropdowns from an explicit whitelist, not the raw enum
- Filter DELETED rows client-side if needed
When it happens
Trigger: GET /api/rpc?deviceId=...&rpcStatus=DELETED (v2: /api/rpc/{deviceId}) passing DELETED explicitly in the status filter.
Common situations: A UI dropdown built straight from the RpcStatus enum values including DELETED; client code iterating all enum constants for filtering; log-driven tooling replaying a status seen on a deleted RPC record.
Related errors
- BAD_REQUEST_PARAMS
- Template is missing
- Target type is not platform users
- BAD_REQUEST_PARAMS
- Invalid scope
AI-assisted analysis of thingsboard/thingsboard@45c30e83fa (2026-08-14).
Data as JSON: /api/errors/78d7be057c65c7e9.
Report an issue: GitHub.