{"record":{"id":"afd1d17db5bc8940","repo":"apache/pulsar","slug":"processing-guarantees-cannot-be-altered-afd1d1","errorCode":null,"errorMessage":"Processing Guarantees cannot be altered","messagePattern":"Processing Guarantees cannot be altered","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SourceConfigUtils.java","lineNumber":414,"sourceCode":"        }\n        if (!StringUtils.isEmpty(newConfig.getSerdeClassName())) {\n            mergedConfig.setSerdeClassName(newConfig.getSerdeClassName());\n        }\n        if (!StringUtils.isEmpty(newConfig.getSchemaType())) {\n            mergedConfig.setSchemaType(newConfig.getSchemaType());\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 (!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.getParallelism() != null) {\n            mergedConfig.setParallelism(newConfig.getParallelism());\n        }\n        if (newConfig.getResources() != null) {\n            mergedConfig\n                    .setResources(ResourceConfigUtils.merge(existingConfig.getResources(), newConfig.getResources()));\n        }\n        if (!StringUtils.isEmpty(newConfig.getArchive())) {\n            mergedConfig.setArchive(newConfig.getArchive());\n        }\n        if (!StringUtils.isEmpty(newConfig.getRuntimeFlags())) {\n            mergedConfig.setRuntimeFlags(newConfig.getRuntimeFlags());\n        }\n        if (!StringUtils.isEmpty(newConfig.getCustomRuntimeOptions())) {\n            mergedConfig.setCustomRuntimeOptions(newConfig.getCustomRuntimeOptions());\n        }\n        if (isBatchSource(existingConfig) != isBatchSource(newConfig)) {","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SourceConfigUtils.java#L396-L432","documentation":"The processing guarantees (at-most-once, at-least-once, effectively-once) of a source cannot be changed after creation, because it affects how state and delivery semantics are managed. validateUpdate rejects any attempt to alter it.","triggerScenarios":"validateUpdate sees newConfig.getProcessingGuarantees() != null and not equal to existingConfig.getProcessingGuarantees().","commonSituations":"Operator tries to strengthen delivery guarantees on a live source via update; config template regenerated with a different default guarantee; tooling that always populates processingGuarantees with the template's value instead of the existing one.","solutions":["Resubmit the update with processingGuarantees either omitted (null) or equal to the existing value","If the guarantee must change, delete and recreate the source with the new guarantee","Update tooling to preserve the existing processingGuarantees on update calls"],"exampleFix":"// before\n{\"processingGuarantees\":\"EFFECTIVELY_ONCE\", ...} // existing is ATLEAST_ONCE\n// after\nomit processingGuarantees from the update payload, or set it to \"ATLEAST_ONCE\"","handlingStrategy":"validation","validationCode":"if (update.getProcessingGuarantees() != null\n    && !update.getProcessingGuarantees().equals(existing.getProcessingGuarantees())) {\n    throw new IllegalArgumentException(\"processingGuarantees is immutable on update\");\n}","typeGuard":null,"tryCatchPattern":"try { SourceConfigUtils.validateUpdate(existing, update); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Processing Guarantees\")) { update.setProcessingGuarantees(null); /* omit from update */ } else { throw e; } }","preventionTips":["Omit processingGuarantees from update payloads unless explicitly unchanged","Choose the right guarantee at creation time; plan recreation if it must change","Don't let templates inject default guarantees into update requests"],"tags":["pulsar-functions","immutable-field","delivery-guarantees"],"backgroundTag":"immutable-field-change","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}