flowable/flowable-engine · error · FlowableObjectNotFoundException
User info with key ' ' does not exists for user ' '.
Error message
User info with key '${key}' does not exists for user '${userId}'. What it means
FlowableObjectNotFoundException thrown by getValidKeyFromRequest when identityService.getUserInfo(userId, key) returns null, i.e. no user info entry exists for the given user and key. All operations on /identity/users/{userId}/info/{key} (GET, PUT, DELETE) validate the key first, so the request is rejected before any mutation. Flowable treats a missing info entry as a not-found resource rather than an empty value.
Solutions
- Verify the key exists: GET identity/users/{userId}/info and confirm the key is in the list before accessing it.
- Correct the key spelling/casing in the request URL.
- If the entry may legitimately not exist, handle the 404 (FlowableObjectNotFoundException) response gracefully instead of treating it as a bug.
- Create the entry first with PUT identity/users/{userId}/info/{key} with a non-null value, then read it.
Example fix
// before (fails when key absent)
GET /identity/users/jdoe/info/email
// after — create or ensure it first
PUT /identity/users/jdoe/info/email
{"value":"jdoe@example.com"}
// then
GET /identity/users/jdoe/info/email Defensive patterns
Strategy: try-catch
Validate before calling
// list existing info entries first and check the key
const res = await fetch(`/identity/users/${userId}/info`);
const entries = await res.json();
if (!entries.some(e => e.key === key)) {
// key does not exist — create it or skip
} Type guard
function infoKeyExists(entries, key) {
return Array.isArray(entries) && entries.some(e => e && e.key === key);
} Try / catch
try {
const res = await fetch(`/identity/users/${userId}/info/${key}`);
if (res.status === 404) {
// FlowableObjectNotFoundException: key does not exist for this user
return null; // treat as 'no value' rather than a failure
}
return await res.json();
} catch (e) { /* network error */ } Prevention
- List all info entries (GET .../info) before addressing a specific key.
- Treat 404 on a single info key as 'absent', not as a client bug.
- Standardize key names/casing across environments.
- Create entries idempotently (PUT) before reading them in setup scripts.
When it happens
Trigger: GET/PUT/DELETE identity/users/{userId}/info/{key} where the user exists but identityService.getUserInfo(userId, key) has never been set for that key, or the entry was deleted earlier. Note: an info entry stored as an empty string may still return non-null; a truly absent key throws.
Common situations: Typos in the info key ('Email' vs 'email'); querying a key on the wrong userId; keys removed by another process or during user cleanup; environments (test vs prod) where the info entry was never created.
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.
Related errors
- Could not find a app model json with id
- Could not find a deployment with id
- Could not find a milestone instance with id
- Could not find a plan item instance with id
- Could not find a resource with id
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f37558de4d7ea727.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/identity/UserInfoResource.java:115
})
@DeleteMapping("/identity/users/{userId}/info/{key}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteUserInfo(@ApiParam(name = "userId") @PathVariable("userId") String userId, @ApiParam(name = "key") @PathVariable("key") String key) {
User user = getUserFromRequest(userId);
if (restApiInterceptor != null) {
restApiInterceptor.deleteUser(user);
}
String validKey = getValidKeyFromRequest(user, key);
identityService.setUserInfo(user.getId(), validKey, null);
}
protected String getValidKeyFromRequest(User user, String key) {
String existingValue = identityService.getUserInfo(user.getId(), key);
if (existingValue == null) {
throw new FlowableObjectNotFoundException("User info with key '" + key + "' does not exists for user '" + user.getId() + "'.", null);
}
return key;
}
}
View on GitHub (pinned to d6d39ce1c6)