flowable/flowable-engine · error · FlowableIllegalArgumentException

Key provided in request body does not match the key in the…

Error message

Key provided in request body does not match the key in the resource URL.

What it means

GroupResource.updateGroup only applies changes when the id in the request body matches the groupId path variable; otherwise it throws FlowableIllegalArgumentException. Group ids are immutable identifiers, so a body that renames or mismatched the URL would either update the wrong record or be ambiguous — the REST layer rejects it instead.

Solutions

  1. Make the body "id" exactly match the {groupId} path variable.
  2. To 'rename' a group, create a new group with the desired id and delete the old one; ids cannot be changed via update.
  3. On the client, serialize the id from the same source used to build the URL.

Example fix

// before
PUT /identity/groups/sales {"id":"marketing","name":"Marketing"}
// after
PUT /identity/groups/sales {"id":"sales","name":"Sales (EU)"}
// renaming requires create-new + delete-old, not a body id change
Defensive patterns

Strategy: validation

Validate before calling

if (!groupId.equals(groupRequest.getId())) {
    throw new IllegalArgumentException("Body id must match URL groupId for PUT /identity/groups/" + groupId);
}

Type guard

boolean idMatchesUrl(String urlId, GroupRequest r) { return r != null && urlId != null && urlId.equals(r.getId()); }

Prevention

When it happens

Trigger: PUT /identity/groups/{groupId} where the JSON body's "id" differs from {groupId}, e.g. PUT /identity/groups/sales with body {"id":"marketing",...}, or the client simply omitted the id field and it deserialized to a different/mismatched value.

Common situations: Attempting to rename a group by changing its id in the body (ids are immutable — create a new group instead); a shared request DTO whose id field was populated with the wrong value; copying a payload built for a POST into a PUT.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/79e7372f5be7b176. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/identity/GroupResource.java:71

    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the group was updated."),
            @ApiResponse(code = 404, message = "Indicates the requested group was not found."),
            @ApiResponse(code = 409, message = "Indicates the requested group was updated simultaneously.")
    })
    @PutMapping(value = "/identity/groups/{groupId}", produces = "application/json")
    public GroupResponse updateGroup(@ApiParam(name = "groupId") @PathVariable String groupId, @RequestBody GroupRequest groupRequest) {
        Group group = getGroupFromRequest(groupId);

        if (groupRequest.getId() == null || groupRequest.getId().equals(group.getId())) {
            if (groupRequest.isNameChanged()) {
                group.setName(groupRequest.getName());
            }
            if (groupRequest.isTypeChanged()) {
                group.setType(groupRequest.getType());
            }
            identityService.saveGroup(group);
        } else {
            throw new FlowableIllegalArgumentException("Key provided in request body does not match the key in the resource URL.");
        }

        return restResponseFactory.createGroupResponse(group);
    }

    @ApiOperation(value = "Delete a group", tags = { "Groups" }, code = 204)
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Indicates the group was found and  has been deleted. Response-body is intentionally empty."),
            @ApiResponse(code = 404, message = "Indicates the requested group does not exist.")
    })
    @DeleteMapping("/identity/groups/{groupId}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteGroup(@ApiParam(name = "groupId") @PathVariable String groupId) {
        Group group = getGroupFromRequest(groupId);
        
        if (restApiInterceptor != null) {
            restApiInterceptor.deleteGroup(group);
        }

View on GitHub (pinned to d6d39ce1c6)