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

  1. Keep the root message's package and name identical; undo the rename in the .proto file and regenerate the descriptor.
  2. If the rename is required, delete the topic schema and re-register the new schema (coordinate so consumers fetch the new schema).
  3. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/05298e90d0efdde4. Report an issue: GitHub.