hs-web/hsweb-framework · error · NotFoundException
Not Found
Error message
Not Found
What it means
A NotFoundException thrown in the doOnNext callback of ReactiveServiceSaveController.update (PUT /{id}) when the underlying service's updateById returns 0 updated rows, meaning no entity with the given path-variable id exists (or none matched authorization-modified entity data). It fires because the requested record was deleted or never existed, and the controller translates the 0-row result into a 404 'Not Found' response rather than silently reporting success.
Solutions
- Verify the entity id exists before calling the update endpoint
- Return create-not-update flow if the record should be created when missing
- Check query conditions (tenant, data scope) that could exclude the row
- Handle 404 on the client and refresh entity state
Example fix
// before service.updateById(id, Mono.just(entity)); // after service.findById(id).switchIfEmpty(Mono.error(new NotFoundException())).then(service.updateById(id, Mono.just(entity)));
Defensive patterns
Strategy: try-catch
Validate before calling
boolean exists = service.createQuery().where("id", id).fetchOne().isPresent();
if (!exists) return Mono.error(new NotFoundException()); Type guard
Mono<Entity> existing = service.findById(id); // proceed only if existing has a value before calling updateById
Try / catch
service.updateById(id, Mono.just(entity))
.doOnNext(i -> { if (i == 0) throw new NotFoundException(); })
.onErrorResume(NotFoundException.class, e -> {
log.warn("update target not found: {}", id);
return Mono.just(false);
}); Prevention
- Check entity existence before update
- Refresh stale ids after deletes
- Scope updates with correct tenant/query conditions
- Return 404 semantics explicitly on the client
When it happens
Trigger: PUT/PATCH to the reactive CRUD endpoint with an id that does not exist in storage, or an entity filtered out by query/permission conditions so updateById matches 0 rows.
Common situations: Client uses a stale or deleted id; wrong tenant/workspace scope filters the row out; race where another request deleted the entity first.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13).
Data as JSON: /api/errors/119c7023fdfc6891.
Report an issue: GitHub.
Appendix: source
Thrown at hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java:180
* }
* </pre>
*
* @param payload payload
* @return 是否成功
*/
@PutMapping("/{id}")
@SaveAction
@Operation(summary = "根据ID修改数据")
default Mono<Boolean> update(@PathVariable K id, @RequestBody Mono<E> payload) {
return Authentication
.currentReactive()
.flatMap(auth -> payload.map(entity -> applyAuthentication(entity, auth)))
.switchIfEmpty(payload)
.flatMap(entity -> getService().updateById(id, Mono.just(entity)))
.doOnNext(i -> {
if (i == 0) {
throw new NotFoundException();
}
})
.thenReturn(true);
}
}
View on GitHub (pinned to b2cfc85a57)