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

  1. Use PUT /management/properties/{name} to update an existing property instead of POST.
  2. Check existence first (GET /management/properties) and skip creation if present.
  3. Make scripts idempotent: treat 409 as success if the value already matches.
  4. 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

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


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)