apache/pulsar · critical · IOException

Incompatible layout version found

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.

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.

Appendix: 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)