apache/pulsar · error · IncompatibleSchemaException

Schema compatibility strategy is ALWAYS_INCOMPATIBLE

Error message

Schema compatibility strategy is ALWAYS_INCOMPATIBLE

What it means

The broker's schema compatibility checker throws IncompatibleSchemaException when the configured compatibility strategy is ALWAYS_INCOMPATIBLE. ALWAYS_INCOMPATIBLE means no schema update is ever considered compatible, so the check rejects every update up front without comparing schema content. It is a deliberate hard stop, not a comparison result.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/schema/SchemaCompatibilityCheck.java:75

            checkCompatible(from, to, strategy);
            return true;
        } catch (IncompatibleSchemaException e) {
            return false;
        }
    }

    SchemaCompatibilityCheck DEFAULT = new SchemaCompatibilityCheck() {

        @Override
        public SchemaType getSchemaType() {
            return SchemaType.NONE;
        }

        @Override
        public void checkCompatible(SchemaData from, SchemaData to, SchemaCompatibilityStrategy strategy)
                throws IncompatibleSchemaException {
            if (strategy == SchemaCompatibilityStrategy.ALWAYS_INCOMPATIBLE) {
                throw new IncompatibleSchemaException("Schema compatibility strategy is ALWAYS_INCOMPATIBLE");
            }
        }

        @Override
        public void checkCompatible(Iterable<SchemaData> from, SchemaData to, SchemaCompatibilityStrategy strategy)
                throws IncompatibleSchemaException {
            if (strategy == SchemaCompatibilityStrategy.ALWAYS_INCOMPATIBLE) {
                throw new IncompatibleSchemaException("Schema compatibility strategy is ALWAYS_INCOMPATIBLE");
            }
        }

    };
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Change the namespace policy: pulsar-admin namespaces set-schema-compatibility-strategy <ns> --strategy BACKWARD (or FORWARD/FULL, incl. _TRANSITIVE variants).
  2. If the schema should never change, do not attempt the update at all; keep the existing schema and version-bump the topic instead.
  3. Verify with pulsar-admin namespaces get-schema-compatibility-strategy which strategy is actually applied before calling the admin API.

Example fix

// before
admin.schemas().createSchema("my-topic", schemaInfo); // ns policy = ALWAYS_INCOMPATIBLE
// after
admin.namespaces().setSchemaCompatibilityStrategy("my-tenant/my-ns",
    SchemaCompatibilityStrategy.BACKWARD);
admin.schemas().createSchema("my-topic", schemaInfo);
Defensive patterns

Strategy: validation

Validate before calling

import org.apache.pulsar.common.policies.data.SchemaCompatibilityStrategy;
if (strategy == SchemaCompatibilityStrategy.ALWAYS_INCOMPATIBLE) {
    throw new IllegalArgumentException(
        "Schema updates are disabled (ALWAYS_INCOMPATIBLE); change the namespace policy first");
}

Type guard

boolean updatable(SchemaCompatibilityStrategy s) {
    return s != null && s != SchemaCompatibilityStrategy.ALWAYS_INCOMPATIBLE;
}

Prevention

When it happens

Trigger: Calling SchemaRegistryService.checkCompatible(SchemaData from, SchemaData to, strategy) (single-schema overload, SchemaCompatibilityCheck.java:75) with strategy == SchemaCompatibilityStrategy.ALWAYS_INCOMPATIBLE, e.g. when updating a topic schema whose namespace policy has schemaCompatibilityStrategy set to ALWAYS_INCOMPATIBLE.

Common situations: Namespace/topic policies were intentionally set to ALWAYS_INCOMPATIBLE to freeze the schema; ops copied a sample policy that disabled evolution; a default strategy template in a multi-tenant setup uses ALWAYS_INCOMPATIBLE; tooling passes null/placeholder strategy resolved to ALWAYS_INCOMPATIBLE.

Related errors


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