apache/pulsar · error · IllegalArgumentException
Runtime cannot be altered
Error message
Runtime cannot be altered
What it means
A function's runtime (JAVA, PYTHON, GO, etc.) is fixed at creation time. validateUpdate throws IllegalArgumentException if an update attempts to change it, since the worker's runtime machinery cannot be swapped in place for a running function.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:1087
if (newConfig.getRetainOrdering() != null && !newConfig.getRetainOrdering()
.equals(existingConfig.getRetainOrdering())) {
throw new IllegalArgumentException("Retain Ordering cannot be altered");
}
if (newConfig.getRetainKeyOrdering() != null && !newConfig.getRetainKeyOrdering()
.equals(existingConfig.getRetainKeyOrdering())) {
throw new IllegalArgumentException("Retain Key Ordering cannot be altered");
}
if (!StringUtils.isEmpty(newConfig.getOutput())) {
mergedConfig.setOutput(newConfig.getOutput());
}
if (newConfig.getUserConfig() != null) {
mergedConfig.setUserConfig(newConfig.getUserConfig());
}
if (newConfig.getSecrets() != null) {
mergedConfig.setSecrets(newConfig.getSecrets());
}
if (newConfig.getRuntime() != null && !newConfig.getRuntime().equals(existingConfig.getRuntime())) {
throw new IllegalArgumentException("Runtime cannot be altered");
}
@SuppressWarnings("deprecation")
boolean autoAckChanged = newConfig.getAutoAck() != null
&& !newConfig.getAutoAck().equals(existingConfig.getAutoAck());
if (autoAckChanged) {
throw new IllegalArgumentException("AutoAck cannot be altered");
}
if (newConfig.getMaxMessageRetries() != null) {
mergedConfig.setMaxMessageRetries(newConfig.getMaxMessageRetries());
}
if (!StringUtils.isEmpty(newConfig.getDeadLetterTopic())) {
mergedConfig.setDeadLetterTopic(newConfig.getDeadLetterTopic());
}
if (!StringUtils.isEmpty(newConfig.getSubName()) && !newConfig.getSubName()
.equals(existingConfig.getSubName())) {
throw new IllegalArgumentException("Subscription Name cannot be altered");
}
if (newConfig.getParallelism() != null) {View on GitHub (pinned to 820761864e)
Solutions
- Do not set runtime (or set it to the existing value) when updating.
- Delete and re-create the function with the new runtime to switch languages.
- Verify the code path building the update config isn't picking up a foreign runtime value.
Example fix
// before update.setRuntime(FunctionConfig.Runtime.PYTHON); // existing is JAVA -> thrown // after admin.functions().deleteFunction(tenant, namespace, name); admin.functions().createFunction(newConfigWithPythonRuntime, pkgFile);
Defensive patterns
Strategy: validation
Validate before calling
FunctionConfig existing = admin.functions().getFunction(tenant, namespace, fnName);
if (update.getRuntime() != null && !update.getRuntime().equals(existing.getRuntime())) {
throw new IllegalStateException("Runtime is immutable; delete and re-create the function");
} Try / catch
try {
admin.functions().updateFunction(update, pkgFile);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Runtime cannot be altered")) { /* fall back to delete+create */ }
else throw e;
} Prevention
- Never set runtime on update configs.
- To change language/runtime, delete and re-create the function.
- Centralize config-building so runtime is only set at creation.
When it happens
Trigger: Calling updateFunction with a FunctionConfig whose getRuntime() is non-null and differs from existingConfig.getRuntime().
Common situations: Rewriting a Java function in Python and trying to update in place; update code that copies runtime from a different config object; tooling that sets runtime explicitly on every submit.
Related errors
- Unsupported Runtime %s
- Log folder creation error
- Unsupported Runtime
- Thread Container only supports Java Runtime
- Function language runtime is either not set or cannot be det
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/148c292867a143a4.
Report an issue: GitHub.