{"record":{"id":"ed3e740aa6271c2d","repo":"apache/pulsar","slug":"subscription-name-cannot-be-altered","errorCode":null,"errorMessage":"Subscription Name cannot be altered","messagePattern":"Subscription Name 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":1103,"sourceCode":"        }\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\");\n        }\n        if (newConfig.getMaxMessageRetries() != null) {\n            mergedConfig.setMaxMessageRetries(newConfig.getMaxMessageRetries());\n        }\n        if (!StringUtils.isEmpty(newConfig.getDeadLetterTopic())) {\n            mergedConfig.setDeadLetterTopic(newConfig.getDeadLetterTopic());\n        }\n        if (!StringUtils.isEmpty(newConfig.getSubName()) && !newConfig.getSubName()\n                .equals(existingConfig.getSubName())) {\n            throw new IllegalArgumentException(\"Subscription Name 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 (newConfig.getWindowConfig() != null) {\n            mergedConfig.setWindowConfig(newConfig.getWindowConfig());\n        }\n        if (newConfig.getTimeoutMs() != null) {\n            mergedConfig.setTimeoutMs(newConfig.getTimeoutMs());\n        }\n        if (newConfig.getCleanupSubscription() != null) {\n            mergedConfig.setCleanupSubscription(newConfig.getCleanupSubscription());\n        }\n        if (!StringUtils.isEmpty(newConfig.getRuntimeFlags())) {","sourceCodeStart":1085,"sourceCodeEnd":1121,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L1085-L1121","documentation":"FunctionConfigUtils.validateUpdate rejects changing the subscription name on an existing function: the subscription identity is fixed at creation, and altering it would orphan the existing subscription state.","triggerScenarios":"Calling updateFunction with a FunctionConfig whose getSubName() is non-empty and differs from existingConfig.getSubName().","commonSituations":"Renaming the subscription to isolate a stuck consumer; update payloads built from scratch that default subName differently from the deployed function; switching between shared and failover naming conventions.","solutions":["Keep the same subscription name on update","Delete the old subscription explicitly if a rename is truly needed"],"exampleFix":"// before\nupdate.setSubName(\"my-function-sub-v2\"); // existing sub differs -> thrown\n// after\nupdate.setSubName(existing.getSubName()); // unchanged","handlingStrategy":"validation","validationCode":"FunctionConfig existing = admin.functions().getFunction(tenant, namespace, fnName);\nif (!StringUtils.isEmpty(update.getSubName()) && !update.getSubName().equals(existing.getSubName())) {\n    update.setSubName(null);\n}","typeGuard":null,"tryCatchPattern":"try {\n    admin.functions().updateFunction(update, pkgFile);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Subscription Name\")) { /* keep existing subName and retry */ }\n    else throw e;\n}","preventionTips":["Never change subName on updates; re-create the function if a new subscription is required.","Build updates from the existing fetched config.","Validate subName equality before calling the update API."],"tags":["pulsar-functions","config-update","subscription"],"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-14T05:17:10.506Z"}