{"record":{"id":"05b90129d9bf6962","repo":"flowable/flowable-engine","slug":"engine-property-propertyname-already-exists","errorCode":null,"errorMessage":"Engine property ${propertyName} already exists","messagePattern":"Engine property (.+?) already exists","errorType":"http","errorClass":"FlowableConflictException","httpStatus":409,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/EnginePropertiesResource.java","lineNumber":110,"sourceCode":"        if (!properties.containsKey(engineProperty)) {\n            throw new FlowableObjectNotFoundException(\"Engine property \" + engineProperty + \" does not exist\");\n        }\n    }\n\n    @ApiOperation(value = \"Create a new engine property\", tags = { \"EngineProperties\" }, code = 201)\n    @ApiResponses(value = {\n        @ApiResponse(code = 201, message = \"Indicates the property is created\"),\n        @ApiResponse(code = 409, message = \"Indicates the property already exists\")\n    })\n    @PostMapping(value = \"/management/engine-properties\", produces = \"application/json\")\n    @ResponseStatus(HttpStatus.CREATED)\n    public void createEngineProperty(@RequestBody PropertyRequestBody propertyRequestBody) {\n        validateAccessToProperties();\n\n        Map<String, String> properties = managementService.getProperties();\n        String propertyName = propertyRequestBody.getName();\n        if (properties.containsKey(propertyName)) {\n            throw new FlowableConflictException(\"Engine property \" + propertyName + \" already exists\");\n        }\n\n        managementService.executeCommand(commandContext -> {\n            PropertyEntityManager propertyEntityManager = CommandContextUtil.getPropertyEntityManager(commandContext);\n            PropertyEntity propertyEntity = propertyEntityManager.create();\n            propertyEntity.setName(propertyName);\n            propertyEntity.setValue(propertyRequestBody.getValue());\n            propertyEntityManager.insert(propertyEntity);\n            return null;\n        });\n    }\n\n    @ApiOperation(value = \"Update an engine property\", tags = { \"EngineProperties\" })\n    @ApiResponses(value = {\n        @ApiResponse(code = 200, message = \"Indicates the property is updated\"),\n        @ApiResponse(code = 404, message = \"Indicates the property is not found\")\n    })\n    @PutMapping(value = \"/management/engine-properties/{engineProperty}\", produces = \"application/json\")","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/EnginePropertiesResource.java#L92-L128","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\ncurl -X POST -H 'Content-Type: application/json' \\\n  -d '{\"name\":\"cfg.customFlag\",\"value\":\"true\"}' \\\n  http://localhost:8080/flowable-rest/management/properties\n// after (update instead of create)\ncurl -X PUT -H 'Content-Type: application/json' \\\n  -d '{\"value\":\"true\"}' \\\n  http://localhost:8080/flowable-rest/management/properties/cfg.customFlag","handlingStrategy":"validation","validationCode":"const props = await fetch(`${base}/management/properties`).then(r => r.json());\nif (props.data.some(p => p.name === newName)) {\n  // update instead of create\n  await fetch(`${base}/management/properties/${encodeURIComponent(newName)}`, { method: 'PUT', body: JSON.stringify({ value }) });\n} else {\n  await createProperty(newName, value);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await createEngineProperty(name, value);\n} catch (e) {\n  if (e.status === 409) await updateEngineProperty(name, value); // idempotent fallback\n  else throw e;\n}","preventionTips":["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."],"tags":["rest-api","conflict","duplicate","engine-property"],"backgroundTag":"file-already-exists","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}