flowable/flowable-engine · error · FlowableConflictException
Engine property already exists
Error message
Engine property ${propertyName} already exists What it means
createEngineProperty checks the engine's existing property map and throws FlowableConflictException when a property with the same name already exists. Engine properties are keyed by unique name in ACT_GE_PROPERTY, so creating a duplicate would violate that uniqueness. The 409-conflict style error tells the caller to update instead of create.
Solutions
- Use PUT /management/properties/{name} to update an existing property instead of POST.
- Check existence first (GET /management/properties) and skip creation if present.
- Make scripts idempotent: treat 409 as success if the value already matches.
- If the property genuinely should not exist, delete it first, then create.
Example fix
// before
curl -X POST -H 'Content-Type: application/json' \
-d '{"name":"cfg.customFlag","value":"true"}' \
http://localhost:8080/flowable-rest/management/properties
// after (update instead of create)
curl -X PUT -H 'Content-Type: application/json' \
-d '{"value":"true"}' \
http://localhost:8080/flowable-rest/management/properties/cfg.customFlag Defensive patterns
Strategy: validation
Validate before calling
const props = await fetch(`${base}/management/properties`).then(r => r.json());
if (props.data.some(p => p.name === newName)) {
// update instead of create
await fetch(`${base}/management/properties/${encodeURIComponent(newName)}`, { method: 'PUT', body: JSON.stringify({ value }) });
} else {
await createProperty(newName, value);
} Try / catch
try {
await createEngineProperty(name, value);
} catch (e) {
if (e.status === 409) await updateEngineProperty(name, value); // idempotent fallback
else throw e;
} Prevention
- Make provisioning scripts idempotent: on conflict, update the value.
- Never re-POST create requests after a timeout without checking existence.
- Serialize property creation across deployments with a lock or single runner.
When it happens
Trigger: POST /management/properties with a PropertyRequestBody whose name matches an existing engine property (e.g. re-running an initialization script, or double-submitting the same create request).
Common situations: Idempotency issues in deployment scripts that POST properties on every run, concurrent provisioning by two clients, or confusion between create (POST) and update (PUT) semantics.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- A group with id '' already exists.
- User '' is already part of group ''.
- Variable ' ' is already present on task ' '.
- Engine property does not exist
- Process definition with id '" + processDefinition.getId() +…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/05b90129d9bf6962.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/EnginePropertiesResource.java:110
if (!properties.containsKey(engineProperty)) {
throw new FlowableObjectNotFoundException("Engine property " + engineProperty + " does not exist");
}
}
@ApiOperation(value = "Create a new engine property", tags = { "EngineProperties" }, code = 201)
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Indicates the property is created"),
@ApiResponse(code = 409, message = "Indicates the property already exists")
})
@PostMapping(value = "/management/engine-properties", produces = "application/json")
@ResponseStatus(HttpStatus.CREATED)
public void createEngineProperty(@RequestBody PropertyRequestBody propertyRequestBody) {
validateAccessToProperties();
Map<String, String> properties = managementService.getProperties();
String propertyName = propertyRequestBody.getName();
if (properties.containsKey(propertyName)) {
throw new FlowableConflictException("Engine property " + propertyName + " already exists");
}
managementService.executeCommand(commandContext -> {
PropertyEntityManager propertyEntityManager = CommandContextUtil.getPropertyEntityManager(commandContext);
PropertyEntity propertyEntity = propertyEntityManager.create();
propertyEntity.setName(propertyName);
propertyEntity.setValue(propertyRequestBody.getValue());
propertyEntityManager.insert(propertyEntity);
return null;
});
}
@ApiOperation(value = "Update an engine property", tags = { "EngineProperties" })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Indicates the property is updated"),
@ApiResponse(code = 404, message = "Indicates the property is not found")
})
@PutMapping(value = "/management/engine-properties/{engineProperty}", produces = "application/json")View on GitHub (pinned to d6d39ce1c6)