apache/kafka · error · IllegalArgumentException
Cannot specify a negative version level.
Error message
Cannot specify a negative version level.
What it means
Thrown by the FeatureUpdate constructor when maxVersionLevel is negative. Version levels are non-negative shorts where 0 is the delete sentinel and positive values are real feature levels; a negative value is never valid and indicates a bug or arithmetic underflow in the caller. The check runs after the maxVersionLevel==0 UPGRADE guard so it catches any value < 0.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/admin/FeatureUpdate.java:78
/**
* @param maxVersionLevel The new maximum version level for the finalized feature.
* a value of zero is special and indicates that the update is intended to
* delete the finalized feature, and should be accompanied by setting
* the upgradeType to safe or unsafe.
* @param upgradeType Indicate what kind of upgrade should be performed in this operation.
* - UPGRADE: upgrading the feature level
* - SAFE_DOWNGRADE: only downgrades which do not result in metadata loss are permitted
* - UNSAFE_DOWNGRADE: any downgrade, including those which may result in metadata loss, are permitted
*/
public FeatureUpdate(final short maxVersionLevel, final UpgradeType upgradeType) {
if (maxVersionLevel == 0 && upgradeType.equals(UpgradeType.UPGRADE)) {
throw new IllegalArgumentException(String.format(
"The upgradeType flag should be set to SAFE_DOWNGRADE or UNSAFE_DOWNGRADE when the provided maxVersionLevel:%d is < 1.",
maxVersionLevel));
}
if (maxVersionLevel < 0) {
throw new IllegalArgumentException("Cannot specify a negative version level.");
}
this.maxVersionLevel = maxVersionLevel;
this.upgradeType = upgradeType;
}
public short maxVersionLevel() {
return maxVersionLevel;
}
public UpgradeType upgradeType() {
return upgradeType;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}View on GitHub (pinned to c31c9215e1)
Solutions
- Clamp computed level values to >= 0 before constructing the FeatureUpdate.
- Validate input from external sources (config, RPC, CLI args) is non-negative before passing it in.
- Use 0 explicitly when you intend deletion (with the appropriate downgrade type).
- Add a unit test asserting FeatureUpdate rejects negative levels to catch regressions.
Example fix
// before
short target = (short) (currentLevel - offset); // can be negative
new FeatureUpdate(target, FeatureUpdate.UpgradeType.UPGRADE);
// after
short target = (short) Math.max(0, currentLevel - offset);
FeatureUpdate.UpgradeType type = target == 0
? FeatureUpdate.UpgradeType.SAFE_DOWNGRADE
: FeatureUpdate.UpgradeType.UPGRADE;
new FeatureUpdate(target, type); Defensive patterns
Strategy: validation
Validate before calling
// maxVersionLevel must be >= 0. Reject negatives before constructing.
short maxVersionLevel = ...;
if (maxVersionLevel < 0) {
throw new IllegalArgumentException(
"maxVersionLevel must be >= 0, got " + maxVersionLevel);
}
FeatureUpdate update = new FeatureUpdate(maxVersionLevel, upgradeType); Type guard
// Guard: only non-negative shorts are valid FeatureUpdate levels.
static boolean isNonNegativeLevel(short level) {
return level >= 0;
} Try / catch
try {
FeatureUpdate update = new FeatureUpdate(maxVersionLevel, upgradeType);
} catch (IllegalArgumentException e) {
// Negative level reached the constructor. Clamp or reject upstream.
log.error("Negative FeatureUpdate level {}: {}", maxVersionLevel, e.getMessage());
} Prevention
- Validate numeric inputs at the API/config boundary before they reach FeatureUpdate.
- Do not cast arbitrary int/long config values to short without a range check; negative ints truncate to negative shorts.
- Centralize FeatureUpdate construction behind a validator so the rule lives in one place.
- Add a precondition (e.g. Guava checkArgument) at the entry point that produces maxVersionLevel.
When it happens
Trigger: Constructing new FeatureUpdate((short) -1, anyType), or passing a short computed from a subtraction, cast, or external input that went negative. Reached from admin clients, tooling, or deserialization paths that build a FeatureUpdate from untrusted numbers.
Common situations: Caller computes (currentLevel - 1) without clamping; short underflow when reading raw bytes; malformed external config feeding a negative value; test fixtures with wrong literals; client parsing a corrupted controller response.
Related errors
- Expected minVersionLevel >= 0, maxVersionLevel >= 0 and maxV
- Partition {partition} was not included in the original reque
- Topic {topic} was not included in the original request
- Topic partition {partition} was not included in the request
- TransactionalId `{transactionalId}` was not included in the
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/c12e77d178f21f5c.json.
Report an issue: GitHub.