apache/kafka · error · IllegalArgumentException
The upgradeType flag should be set to SAFE_DOWNGRADE or UNSA
Error message
The upgradeType flag should be set to SAFE_DOWNGRADE or UNSAFE_DOWNGRADE when the provided maxVersionLevel:%d is < 1.
What it means
Thrown by the FeatureUpdate constructor when maxVersionLevel is 0 (the special 'delete this finalized feature' sentinel) but upgradeType is still UPGRADE. Deletion is a downgrade operation, so the client rejects the contradictory combination before it ever reaches the broker. The 0 level has no meaning as an upgrade target.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/admin/FeatureUpdate.java:73
} else {
return UNKNOWN;
}
}
}
/**
* @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;
}
View on GitHub (pinned to 996fb4585a)
Solutions
- If your intent is to delete the finalized feature, pass UpgradeType.SAFE_DOWNGRADE or UpgradeType.UNSAFE_DOWNGRADE with maxVersionLevel 0.
- If your intent is to upgrade, set maxVersionLevel to a positive value (>= 1) representing the target level.
- Centralize FeatureUpdate construction behind a helper that derives upgradeType from the level so 0 always maps to a downgrade type.
Example fix
// before new FeatureUpdate((short) 0, FeatureUpdate.UpgradeType.UPGRADE); // after (delete the feature) new FeatureUpdate((short) 0, FeatureUpdate.UpgradeType.SAFE_DOWNGRADE);
Defensive patterns
Strategy: validation
Validate before calling
short level = ...;
FeatureUpdate.UpgradeType type = (level == 0)
? FeatureUpdate.UpgradeType.SAFE_DOWNGRADE
: FeatureUpdate.UpgradeType.UPGRADE;
// safe to construct:
new FeatureUpdate(level, type); Type guard
static boolean isLegalFeatureUpdateArgs(short level, FeatureUpdate.UpgradeType type) {
if (level < 0) return false;
if (level == 0 && type == FeatureUpdate.UpgradeType.UPGRADE) return false;
return true;
} Try / catch
try {
new FeatureUpdate(level, upgradeType);
} catch (IllegalArgumentException e) {
// derive a safe upgradeType from level and retry, or surface to caller
} Prevention
- Never pair level 0 with UPGRADE; treat 0 as 'delete' and pair it with a downgrade type.
- Encapsulate FeatureUpdate construction in a single factory method that derives the upgrade type from the level.
When it happens
Trigger: Constructing new FeatureUpdate((short) 0, FeatureUpdate.UpgradeType.UPGRADE), or building a FeatureUpdate from deserialized/user input where the upgradeType defaulted to UPGRADE while the requested level was 0. Calling AdminClient.describeFeatures/alterFeatures machinery that builds a FeatureUpdate with level 0 and UPGRADE.
Common situations: Automation that deletes a finalized feature by setting its level to 0 but forgets to switch the upgrade type; copy-pasting an upgrade code path to perform a deletion; UI/config tooling that lets a user pick level 0 with an 'upgrade' intent.
Related errors
- Cannot specify a negative version level.
- Expected minVersionLevel >= 0, maxVersionLevel >= 0 and maxV
- TransactionalId `{transactionalId}` was not included in the
- Offsets for consumer group '{groupId}' were not requested.
- List Offsets for partition "{partition}" was not attempted
AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11).
Data as JSON: /api/errors/81af389c0e0b04af.
Report an issue: GitHub.