{"record":{"id":"54e29bace7d6f462","repo":"apache/pulsar","slug":"retain-ordering-cannot-be-altered-54e29b","errorCode":null,"errorMessage":"Retain Ordering cannot be altered","messagePattern":"Retain Ordering cannot be altered","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java","lineNumber":698,"sourceCode":"                finalMergedConfig.getInputSpecs().put(topicName, consumerConfig);\n            });\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.getConfigs() != null) {\n            mergedConfig.setConfigs(newConfig.getConfigs());\n        }\n        if (newConfig.getSecrets() != null) {\n            mergedConfig.setSecrets(newConfig.getSecrets());\n        }\n        if (newConfig.getParallelism() != null) {\n            mergedConfig.setParallelism(newConfig.getParallelism());\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        @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\");\n        }\n        if (newConfig.getResources() != null) {\n            mergedConfig\n                    .setResources(ResourceConfigUtils.merge(existingConfig.getResources(), newConfig.getResources()));\n        }\n        if (newConfig.getTimeoutMs() != null) {\n            mergedConfig.setTimeoutMs(newConfig.getTimeoutMs());\n        }","sourceCodeStart":680,"sourceCodeEnd":716,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java#L680-L716","documentation":"Thrown by SinkConfigUtils.validateUpdate when retainOrdering is set and differs from the existing sink's value. Ordering retention is an immutable deployment property; flipping it via update would change how messages are dispatched to sink instances.","triggerScenarios":"Updating a sink with getRetainOrdering() non-null and not equal to the deployed value, e.g. turning ordering on for an existing unordered sink.","commonSituations":"Developer enables retainOrdering to fix out-of-order processing via update instead of recreate; shared config template sets retainOrdering: true while the deployed sink was created without it.","solutions":["Set retainOrdering to the same value as the existing sink, or leave it null","If ordering must change, delete and recreate the sink","Inspect the deployed config's retainOrdering before updating"],"exampleFix":"// before\nsinkConfig.setRetainOrdering(true); // deployed sink has false\nadmin.sinks().updateSink(tenant, namespace, sinkConfig, null);\n// after\nsinkConfig.setRetainOrdering(false); // matches existing\nadmin.sinks().updateSink(tenant, namespace, sinkConfig, null);","handlingStrategy":"validation","validationCode":"if (newCfg.getRetainOrdering() != null\n    && !newCfg.getRetainOrdering().equals(existing.getRetainOrdering())) {\n    throw new IllegalArgumentException(\"retainOrdering is immutable\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    admin.sinks().updateSink(tenant, namespace, cfg, null);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Retain Ordering cannot be altered\")) { /* revert retainOrdering */ }\n    else throw e;\n}","preventionTips":["Leave retainOrdering null on updates","Recreate the sink if ordering semantics must change","Keep template configs aligned with deployed values"],"tags":["pulsar","functions","config-validation","immutable-field"],"backgroundTag":"immutable-config-field-update","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"}