apache/kafka · error · IllegalArgumentException
Unknown isolation level " + id
Error message
Unknown isolation level " + id
What it means
Thrown by IsolationLevel.forId(byte) when a caller (typically request/response deserialization) asks for the IsolationLevel matching a byte id that is neither 0 (READ_UNCOMMITTED) nor 1 (READ_COMMITTED). The message is built by string concatenation ("Unknown isolation level " + id) so the offending numeric id appears in the text. It indicates an unexpected isolation level code on the wire, almost always a version mismatch or a malformed/mock payload rather than user config (users set isolation.level by name).
Source
Thrown at clients/src/main/java/org/apache/kafka/common/IsolationLevel.java:45
private final byte id;
IsolationLevel(byte id) {
this.id = id;
}
public byte id() {
return id;
}
public static IsolationLevel forId(byte id) {
switch (id) {
case 0:
return READ_UNCOMMITTED;
case 1:
return READ_COMMITTED;
default:
throw new IllegalArgumentException("Unknown isolation level " + id);
}
}
@Override
public String toString() {
return super.toString().toLowerCase(Locale.ROOT);
}
}
View on GitHub (pinned to c31c9215e1)
Solutions
- Align client and broker versions to a supported combination; check broker and client release notes for isolation-level protocol changes.
- If using a proxy/SDK fork, verify it only emits isolation level 0 or 1 on the wire.
- When constructing requests programmatically, use IsolationLevel.READ_COMMITTED/READ_UNCOMMITTED constants (or the isolation.level config) instead of raw bytes.
- For test fixtures, source the byte from IsolationLevel.forId/id() rather than hardcoding.
Example fix
// before IsolationLevel lvl = IsolationLevel.forId((byte) 7); // throws 298 // after IsolationLevel lvl = IsolationLevel.READ_COMMITTED; // id == 1 byte wire = lvl.id(); // safe to serialize
Defensive patterns
Strategy: validation
Validate before calling
// Validate the byte id before calling IsolationLevel.forId:
byte candidate = id;
if (candidate != 0 && candidate != 1) {
throw new IllegalArgumentException("Invalid isolation level id: " + candidate
+ "; must be 0 (READ_UNCOMMITTED) or 1 (READ_COMMITTED)");
}
IsolationLevel level = IsolationLevel.forId(candidate); Type guard
import org.apache.kafka.common.IsolationLevel;
public static boolean isValidIsolationLevel(byte id) {
return id == IsolationLevel.READ_UNCOMMITTED.id() || id == IsolationLevel.READ_COMMITTED.id();
}
public static java.util.Optional<IsolationLevel> safeIsolationLevel(byte id) {
return isValidIsolationLevel(id)
? java.util.Optional.of(IsolationLevel.forId(id))
: java.util.Optional.empty();
} Try / catch
try {
IsolationLevel level = IsolationLevel.forId(id);
} catch (IllegalArgumentException e) {
// Default defensively or reject; isolation levels are not something to guess at.
throw new IllegalArgumentException("Unsupported isolation level id " + id
+ "; only 0 (READ_UNCOMMITTED) and 1 (READ_COMMITTED) are valid", e);
} Prevention
- Do not persist isolation levels as raw bytes without schema validation; serialize the name instead.
- At every external boundary (config files, wire protocols, user input) restrict to the two known values.
- Prefer IsolationLevel.valueOf(String) from a controlled name list, or hard-code to READ_COMMITTED for consumers unless you have a specific reason.
When it happens
Trigger: Deserialization of a FetchRequest/FetchResponse or ListOffsets request whose isolation_level field is outside {0,1}; a broker-client version skew where one side sends a value the other enum doesn't recognize; hand-crafted protocol bytes in tests; a proxy/middleware rewriting the field incorrectly.
Common situations: Mixing client and broker versions across an unsupported range; using a non-Apache Kafka broker or proxy that emits a non-standard isolation level code; mocks/fuzz tests that fabricate FetchRequest data; misbehaving SDK fork that added an enum value not understood by standard clients.
Related errors
- Value %s must be one of %s
- Unknown rebalance protocol id: {id}
- Buffer underflow while parsing consumer protocol's header
- Malformed consumer protocol subscription
- Malformed consumer protocol assignment
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/119d8abb85077204.json.
Report an issue: GitHub.