{"record":{"id":"76f788b2e262fe5a","repo":"apache/pulsar","slug":"retain-key-ordering-cannot-be-altered","errorCode":null,"errorMessage":"Retain Key Ordering cannot be altered","messagePattern":"Retain Key Ordering cannot be altered","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java","lineNumber":1075,"sourceCode":"        }\n        if (!StringUtils.isEmpty(newConfig.getOutputSchemaType()) && !newConfig.getOutputSchemaType()\n                .equals(existingConfig.getOutputSchemaType())) {\n            throw new IllegalArgumentException(\"Output Schema mismatch\");\n        }\n        if (!StringUtils.isEmpty(newConfig.getLogTopic())) {\n            mergedConfig.setLogTopic(newConfig.getLogTopic());\n        }\n        if (newConfig.getProcessingGuarantees() != null && !newConfig.getProcessingGuarantees()\n                .equals(existingConfig.getProcessingGuarantees())) {\n            throw new IllegalArgumentException(\"Processing Guarantees cannot be altered\");\n        }\n        if (newConfig.getRetainOrdering() != null && !newConfig.getRetainOrdering()\n                .equals(existingConfig.getRetainOrdering())) {\n            throw new IllegalArgumentException(\"Retain Ordering cannot be altered\");\n        }\n        if (newConfig.getRetainKeyOrdering() != null && !newConfig.getRetainKeyOrdering()\n                .equals(existingConfig.getRetainKeyOrdering())) {\n            throw new IllegalArgumentException(\"Retain Key Ordering cannot be altered\");\n        }\n        if (!StringUtils.isEmpty(newConfig.getOutput())) {\n            mergedConfig.setOutput(newConfig.getOutput());\n        }\n        if (newConfig.getUserConfig() != null) {\n            mergedConfig.setUserConfig(newConfig.getUserConfig());\n        }\n        if (newConfig.getSecrets() != null) {\n            mergedConfig.setSecrets(newConfig.getSecrets());\n        }\n        if (newConfig.getRuntime() != null && !newConfig.getRuntime().equals(existingConfig.getRuntime())) {\n            throw new IllegalArgumentException(\"Runtime cannot be altered\");\n        }\n        @SuppressWarnings(\"deprecation\")\n        boolean autoAckChanged = newConfig.getAutoAck() != null\n                && !newConfig.getAutoAck().equals(existingConfig.getAutoAck());\n        if (autoAckChanged) {\n            throw new IllegalArgumentException(\"AutoAck cannot be altered\");","sourceCodeStart":1057,"sourceCodeEnd":1093,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L1057-L1093","documentation":"validateUpdate treats retainKeyOrdering as an immutable function property. Updating a function with a different retainKeyOrdering value than the existing one throws IllegalArgumentException, because key-ordering semantics cannot be changed for an already-registered function.","triggerScenarios":"Calling updateFunction with a FunctionConfig where getRetainKeyOrdering() is non-null and does not equal the existing config's value.","commonSituations":"Toggling key ordering while debugging out-of-order keyed messages; update payloads generated from templates that set retainKeyOrdering explicitly and differ from the deployed function.","solutions":["Leave retainKeyOrdering as-is (null or equal to the existing value) in the update request.","Delete and re-create the function if key-ordering behavior must change.","Fetch the current config with getFunction and only modify allowed fields before submitting."],"exampleFix":"// before\nnewConfig.setRetainKeyOrdering(true); // existing was false -> thrown\n// after\nnewConfig.setRetainKeyOrdering(null); // or keep existing value","handlingStrategy":"validation","validationCode":"FunctionConfig existing = admin.functions().getFunction(tenant, namespace, fnName);\nif (update.getRetainKeyOrdering() != null && !update.getRetainKeyOrdering().equals(existing.getRetainKeyOrdering())) {\n    update.setRetainKeyOrdering(null);\n}","typeGuard":null,"tryCatchPattern":"try {\n    admin.functions().updateFunction(update, pkgFile);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Retain Key Ordering\")) { /* clear field and retry */ }\n    else throw e;\n}","preventionTips":["Treat retainKeyOrdering as create-only; never set it in updates.","Build update configs from the fetched existing config.","Document immutable fields in any internal deploy tooling."],"tags":["pulsar-functions","config-update","immutable-field"],"backgroundTag":"immutable-config-field","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}