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
- Inspect the LAYOUT znode content and compare its type/version with what your Pulsar version expects.
- Align cluster components to a single Pulsar/BookKeeper version that writes the expected layout.
- If the store belongs to another cluster, reconfigure the ledgers/metadata paths instead of sharing it.
- 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
- Keep all brokers on a Pulsar version that writes the expected LAYOUT type/version.
- Do not share a metadata store across clusters with different versions.
- Audit LAYOUT znode content after restores or migrations.
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
- Invalid data found
- IOException
- LedgerLayoutExistsException
- Incompatible layout version found : ${factoryVersion}
- RuntimeException
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b8ca5213f87782a5.
Report an issue: GitHub.