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

  1. If your intent is to delete the finalized feature, pass UpgradeType.SAFE_DOWNGRADE or UpgradeType.UNSAFE_DOWNGRADE with maxVersionLevel 0.
  2. If your intent is to upgrade, set maxVersionLevel to a positive value (>= 1) representing the target level.
  3. 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

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


AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11). Data as JSON: /api/errors/81af389c0e0b04af. Report an issue: GitHub.