apache/pulsar · error · IncompatibleSchemaException
Protobuf root message change is not allowed under the '%s' s
Error message
Protobuf root message change is not allowed under the '%s' strategy. Original message name: '%s', new message name: '%s'.
What it means
Under BACKWARD, FORWARD, or FULL strategies, a Protobuf Native schema may not change its root message's full name: the descriptor of the new schema must resolve to the same fully-qualified message name as the existing one. Renaming or moving the root message breaks wire/semantic identity for existing consumers, so it is rejected.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/schema/ProtobufNativeSchemaCompatibilityCheck.java:70
case ALWAYS_COMPATIBLE:
return;
default:
throw new IncompatibleSchemaException("Unknown SchemaCompatibilityStrategy.");
}
}
@Override
public void checkCompatible(Iterable<SchemaData> from, SchemaData to, SchemaCompatibilityStrategy strategy)
throws IncompatibleSchemaException {
for (SchemaData schemaData : from) {
checkCompatible(schemaData, to, strategy);
}
}
private void checkRootMessageChange(Descriptor fromDescriptor, Descriptor toDescriptor,
SchemaCompatibilityStrategy strategy) throws IncompatibleSchemaException {
if (!fromDescriptor.getFullName().equals(toDescriptor.getFullName())) {
throw new IncompatibleSchemaException("Protobuf root message change is not allowed under the '"
+ strategy + "' strategy. Original message name: '" + fromDescriptor.getFullName()
+ "', new message name: '" + toDescriptor.getFullName() + "'.");
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Keep the root message's package and name identical; undo the rename in the .proto file and regenerate the descriptor.
- If the rename is required, delete the topic schema and re-register the new schema (coordinate so consumers fetch the new schema).
- Set strategy to ALWAYS_COMPATIBLE only if you truly accept unvalidated root-message changes.
Example fix
// before
package com.old; message Event { ... } // full name com.old.Event
// after
package com.old; message Event { ... } // unchanged root; evolve fields only
// or new root: message EventV2 { ... } in a NEW topic schema registration Defensive patterns
Strategy: validation
Validate before calling
Descriptor from = existingProtoDescriptor;
Descriptor to = newProtoDescriptor;
if (!from.getFullName().equals(to.getFullName())) {
throw new IllegalArgumentException("Protobuf root message changed: " + from.getFullName() + " -> " + to.getFullName());
} Type guard
boolean sameRootMessage(Descriptor a, Descriptor b) {
return a != null && b != null && a.getFullName().equals(b.getFullName());
} Try / catch
try {
admin.schemas().createSchema(topic, protoNativeSchemaInfo);
} catch (PulsarAdminException e) {
if (e.getMessage().contains("Protobuf root message change is not allowed")) {
// restore original message/package name or re-register schema deliberately
}
} Prevention
- Treat proto package and root message name as immutable once registered.
- Never rename the root message to 'evolve' a schema; add fields instead.
- Run a CI check comparing descriptor full names against the deployed topic schema.
- For genuine renames, plan a new topic and consumer migration.
When it happens
Trigger: checkRootMessageChange invoked from checkCompatible when fromDescriptor.getFullName() != toDescriptor.getFullName() — e.g. the .proto root message was renamed, repackaged (package change alters the full name), or a different message was chosen as the schema root.
Common situations: Refactoring a proto package (com.old.Msg -> com.new.Msg) without realizing the full name changes; renaming the root message class; uploading a schema generated from a different root message while consumers still use the old one.
Related errors
- Unknown SchemaCompatibilityStrategy.
- deserialize ProtobufNative Schema failed
- protobuf root message descriptor is null, please recheck roo
- The topic has a max partition index of %d, the number of par
- entryFilterNames can't be empty. To remove entry filters use
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/05298e90d0efdde4.
Report an issue: GitHub.