apache/kafka · error · IllegalArgumentException

Illegal MetadataRecoveryStrategy: null

Error message

Illegal MetadataRecoveryStrategy: null

What it means

IllegalArgumentException thrown by MetadataRecoveryStrategy.forName when the supplied strategy name is null. The enum has only two valid names ('none', 'rebootstrap'); a null name cannot be matched, so the constructor refuses it before valueOf is even attempted. It protects NetworkClient initialisation (which reads metadata.recovery.strategy) from an undefined recovery mode.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/MetadataRecoveryStrategy.java:36

import java.util.Locale;

/**
 * Defines the strategies which clients can follow to deal with the situation when none of the known nodes is available.
 */
public enum MetadataRecoveryStrategy {
    NONE("none"),
    REBOOTSTRAP("rebootstrap");

    public final String name;

    MetadataRecoveryStrategy(String name) {
        this.name = name;
    }

    public static MetadataRecoveryStrategy forName(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Illegal MetadataRecoveryStrategy: null");
        }
        try {
            return MetadataRecoveryStrategy.valueOf(name.toUpperCase(Locale.ROOT));
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Illegal MetadataRecoveryStrategy: " + name);
        }
    }
}

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Set metadata.recovery.strategy to one of the documented values: 'none' (default) or 'rebootstrap'.
  2. If building configs in code, ensure the value is non-null before passing to the client (filter out nulls).
  3. If the value is optional in your config layer, default it to 'none' rather than letting null propagate.

Example fix

// before
props.put("metadata.recovery.strategy", null); // NPE-prone, later throws
// after
props.put("metadata.recovery.strategy", "none");
Defensive patterns

Strategy: type-guard

Validate before calling

// metadata.recovery.strategy config must be "none" or "rebootstrap"
// (case-insensitive). Pre-validate the config string:
import java.util.Locale;
import java.util.Set;

static final Set<String> VALID = Set.of("none", "rebootstrap");

static String normalizeRecoveryStrategy(String raw) {
    if (raw == null)
        throw new IllegalArgumentException(
            "metadata.recovery.strategy is null; expected one of " + VALID);
    String norm = raw.trim().toLowerCase(Locale.ROOT);
    if (!VALID.contains(norm))
        throw new IllegalArgumentException(
            "metadata.recovery.strategy='" + raw + "' is not in " + VALID);
    return norm;
}
// props.put("metadata.recovery.strategy", normalizeRecoveryStrategy(raw));

Type guard

static boolean isValidRecoveryStrategy(String raw) {
    if (raw == null) return false;
    String n = raw.trim().toLowerCase(Locale.ROOT);
    return n.equals("none") || n.equals("rebootstrap");
}

Try / catch

// Thrown by MetadataRecoveryStrategy.forName during client construction.
try {
    admin = AdminClient.create(props);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Illegal MetadataRecoveryStrategy")) {
        // Strip the bad value and let the client fall back to its default
        // (DEFAULT_METADATA_RECOVERY_STRATEGY == REBOOTSTRAP), or fail loud:
        props.remove("metadata.recovery.strategy");
        // then decide: retry once without it, or surface to the operator.
        throw new ConfigurationException(e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Setting 'metadata.recovery.strategy' to null, an empty string is not null but a genuinely null config value (e.g. programmatic Map.put(key, null)), or calling forName(null) directly. Reached via ClientUtils.createNetworkClient when building the NetworkClient.

Common situations: Programmatically building configs with a null value, a properties file with the key present but unassigned being parsed as null, a custom config provider returning null, or test code passing null instead of the string literal 'none'.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/32d0abf795e14558.json. Report an issue: GitHub.