apache/pulsar · error · IllegalArgumentException
Namespaces differ
Error message
Namespaces differ
What it means
validateUpdate requires the namespace of the source to remain unchanged across updates. Sources are addressed by tenant/namespace/name; changing the namespace would repoint the source's identity and topics, so it is rejected.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SourceConfigUtils.java:386
}
}
return new ExtractedSourceDetails(sourceClassName, typeArg.asErasure().getTypeName());
}
@SneakyThrows
public static SourceConfig clone(SourceConfig sourceConfig) {
return ObjectMapperFactory.getMapper().reader().readValue(
ObjectMapperFactory.getMapper().writer().writeValueAsBytes(sourceConfig), SourceConfig.class);
}
public static SourceConfig validateUpdate(SourceConfig existingConfig, SourceConfig newConfig) {
SourceConfig mergedConfig = clone(existingConfig);
if (!existingConfig.getTenant().equals(newConfig.getTenant())) {
throw new IllegalArgumentException("Tenants differ");
}
if (!existingConfig.getNamespace().equals(newConfig.getNamespace())) {
throw new IllegalArgumentException("Namespaces differ");
}
if (!existingConfig.getName().equals(newConfig.getName())) {
throw new IllegalArgumentException("Function Names differ");
}
if (!StringUtils.isEmpty(newConfig.getClassName())) {
mergedConfig.setClassName(newConfig.getClassName());
}
if (!StringUtils.isEmpty(newConfig.getTopicName())) {
mergedConfig.setTopicName(newConfig.getTopicName());
}
if (!StringUtils.isEmpty(newConfig.getSerdeClassName())) {
mergedConfig.setSerdeClassName(newConfig.getSerdeClassName());
}
if (!StringUtils.isEmpty(newConfig.getSchemaType())) {
mergedConfig.setSchemaType(newConfig.getSchemaType());
}
if (newConfig.getConfigs() != null) {
mergedConfig.setConfigs(newConfig.getConfigs());View on GitHub (pinned to 820761864e)
Solutions
- Resubmit the update with namespace identical to the existing source's namespace
- Call the update API on the correct tenant/namespace where the source lives
- To relocate the source, delete and recreate it in the target namespace
Example fix
// before
{"tenant":"t1","namespace":"ns2","name":"src1", ...}
// after
{"tenant":"t1","namespace":"ns1","name":"src1", ...} Defensive patterns
Strategy: validation
Validate before calling
if (!Objects.equals(existing.getNamespace(), update.getNamespace())) {
throw new IllegalArgumentException("namespace is immutable on update");
} Try / catch
try { SourceConfigUtils.validateUpdate(existing, update); } catch (IllegalArgumentException e) { if (e.getMessage().equals("Namespaces differ")) { update.setNamespace(existing.getNamespace()); } else { throw e; } } Prevention
- Call the update API on the exact tenant/namespace where the source was created
- Preserve the namespace field from the existing config in update payloads
- Avoid namespace refactors in shared templates without recreating sources
When it happens
Trigger: validateUpdate is given a newConfig whose getNamespace() differs from existingConfig.getNamespace(), e.g. an update request submitted under a different namespace than where the source was created.
Common situations: Submitting the update against the wrong namespace endpoint while the config body names the original namespace (or vice versa); renaming/refactoring namespaces in templates; moving sources during environment migration.
Related errors
- Tenants differ
- Namespaces differ
- Function Names differ
- Input Topics cannot be altered
- isRegexPattern for input topic
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/e0a80ab1a23bf2a0.
Report an issue: GitHub.