apache/pulsar · critical · IOException

Incompatible layout version found : ${factoryVersion}

Error message

Incompatible layout version found : ${factoryVersion}

What it means

PulsarLedgerManagerFactory.initialize reads the stored layout version from the metadata store and requires it to equal CUR_VERSION. If the metadata store holds a layout written by a different (older or newer) BookKeeper/Pulsar version, initialization aborts with this IOException to prevent corrupting ledgers metadata with an incompatible format.

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerManagerFactory.java:61

    private static final int CUR_VERSION = 1;

    @SuppressWarnings("rawtypes")
    private AbstractConfiguration conf;
    private MetadataStoreExtended store;
    private String ledgerRootPath;

    @SuppressWarnings("rawtypes")
    @Override
    public LedgerManagerFactory initialize(AbstractConfiguration conf, LayoutManager layoutManager,
                                           int factoryVersion) throws IOException {

        checkArgument(layoutManager instanceof PulsarLayoutManager);

        PulsarLayoutManager pulsarLayoutManager = (PulsarLayoutManager) layoutManager;

        if (CUR_VERSION != factoryVersion) {
            throw new IOException("Incompatible layout version found : " + factoryVersion);
        }
        this.conf = conf;
        this.store = pulsarLayoutManager.getStore();
        this.ledgerRootPath = pulsarLayoutManager.getLedgersRootPath();
        return this;
    }

    @Override
    public void close() throws IOException {
        // since metadata store instance is passed from outside
        // we don't need to close it here
    }

    @Override
    public int getCurrentVersion() {
        return CUR_VERSION;
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Check the stored layout version in the metadata store (LAYOUT znode under the ledgers root) and align your Pulsar/BookKeeper version with it.
  2. Complete a proper rolling upgrade so all components use the version that wrote the layout.
  3. If the store is stale test/dev data, re-provision the ledgers root (nuke and re-create) after confirming no ledgers are needed.
  4. Never hand-edit the layout znode; use supported migration/upgrade tooling.
Defensive patterns

Strategy: validation

Validate before calling

byte[] layout = store.get(layoutPath).join().get().getValue();
// decode the stored factory version and assert it matches the expected CUR_VERSION before initialize()

Try / catch

try {
    factory.initialize(conf, layoutManager, layoutManager, 1 /* current layout version */);
} catch (IOException e) {
    throw new IllegalStateException("Metadata store layout version incompatible with this build: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling LedgerManagerFactory.initialize when the LAYOUT znode in the metadata store contains a factory version != CUR_VERSION — typically after upgrading or downgrading the broker/bookkeeper stack or pointing a cluster at a store created by another version.

Common situations: Rolling upgrades with mixed versions; reusing a metadata store from an old Pulsar deployment with a new broker; restoring a metadata snapshot from a different release; running a client against a cluster provisioned by a much newer Pulsar.

Related errors


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