apache/pulsar · critical · ReplicationException.CompatibilityException

Incompatible layout found (LAYOUT:1)

Error message

Incompatible layout found (LAYOUT:1)

What it means

checkLayout parses the stored ledger-rereplication layout and requires type == LAYOUT and version == LAYOUT_VERSION. If the stored layout declares a different type or version, a ReplicationException.CompatibilityException with this message is thrown, refusing to run auto-replication against an incompatible layout.

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java:204

                LedgerRereplicationLayoutFormat layoutFormat = new LedgerRereplicationLayoutFormat();
                layoutFormat.setType(LAYOUT).setVersion(LAYOUT_VERSION);
                try {
                    store.put(layoutPath, layoutFormat.toTextFormat().getBytes(UTF_8), Optional.of(-1L)).get();
                } catch (ExecutionException | InterruptedException e) {
                    if (!(e.getCause() instanceof MetadataStoreException.BadVersionException)) {
                        throw new RuntimeException(e);
                    }
                }
            } else {
                byte[] layoutData = store.get(layoutPath).join().get().getValue();

                LedgerRereplicationLayoutFormat layout = new LedgerRereplicationLayoutFormat();

                try {
                    layout.parseFromTextFormat(layoutData);
                    if (!layout.getType().equals(LAYOUT)
                            || layout.getVersion() != LAYOUT_VERSION) {
                        throw new ReplicationException.CompatibilityException(
                                "Incompatible layout found (" + LAYOUT + ":" + LAYOUT_VERSION + ")");
                    }
                } catch (RuntimeException pe) {
                    throw new ReplicationException.CompatibilityException(
                            "Invalid data found", pe);
                }
                break;
            }
        }
    }

    private long getLedgerId(String path) throws NumberFormatException {
        Matcher m = ID_EXTRACTION_PATTERN.matcher(path);
        if (m.find()) {
            return Long.parseLong(m.group(1));
        } else {
            throw new NumberFormatException("Couldn't find ledgerid in path");
        }

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the LAYOUT znode content and compare its type/version with what your Pulsar version expects.
  2. Align cluster components to a single Pulsar/BookKeeper version that writes the expected layout.
  3. If the store belongs to another cluster, reconfigure the ledgers/metadata paths instead of sharing it.
  4. Only remove/re-create the layout znode if you are certain no underreplication state is needed (e.g. fresh cluster).
Defensive patterns

Strategy: validation

Validate before calling

byte[] data = store.get(layoutPath).join().get().getValue();
LedgerRereplicationLayoutFormat layout = new LedgerRereplicationLayoutFormat().parseFromTextFormat(data);
assert "UnderreplicationLedger".equals(layout.getType()) && layout.getVersion() == 1;

Try / catch

try {
    urManager.checkLayout();
} catch (ReplicationException.CompatibilityException e) {
    throw new IllegalStateException("Underreplication layout incompatible; align cluster versions: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Starting a broker whose PulsarLedgerUnderreplicationManager reads a LAYOUT znode written with a different type string or version number — mixed cluster versions, restored metadata from another deployment, or manual edits to the layout znode.

Common situations: Rolling upgrades with incompatible metadata formats; pointing brokers at a metadata store belonging to a different BookKeeper/Pulsar cluster; snapshot restores from backups of other versions.

Related errors


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