{"id":"5fb3a154949aa449","repo":"apache/kafka","slug":"illegal-metadatarecoverystrategy-name","errorCode":null,"errorMessage":"Illegal MetadataRecoveryStrategy: {name}","messagePattern":"Illegal MetadataRecoveryStrategy: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/MetadataRecoveryStrategy.java","lineNumber":41,"sourceCode":" */\npublic enum MetadataRecoveryStrategy {\n    NONE(\"none\"),\n    REBOOTSTRAP(\"rebootstrap\");\n\n    public final String name;\n\n    MetadataRecoveryStrategy(String name) {\n        this.name = name;\n    }\n\n    public static MetadataRecoveryStrategy forName(String name) {\n        if (name == null) {\n            throw new IllegalArgumentException(\"Illegal MetadataRecoveryStrategy: null\");\n        }\n        try {\n            return MetadataRecoveryStrategy.valueOf(name.toUpperCase(Locale.ROOT));\n        } catch (IllegalArgumentException e) {\n            throw new IllegalArgumentException(\"Illegal MetadataRecoveryStrategy: \" + name);\n        }\n    }\n}\n","sourceCodeStart":23,"sourceCodeEnd":45,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/MetadataRecoveryStrategy.java#L23-L45","documentation":"Thrown by MetadataRecoveryStrategy.forName(String) when the supplied strategy name is not null but does not match one of the enum constants (NONE, REBOOTSTRAP). The client uses this strategy to decide how to recover when every known broker node is unreachable. The IllegalArgumentException is raised by valueOf() after upper-casing the input, so it fires for any typo, unknown token, or unsupported value.","triggerScenarios":"Client config property metadata recovery strategy is set to a string other than 'none' or 'rebootstrap' (case-insensitive). It is resolved via MetadataRecoveryStrategy.forName during NetworkClient construction / metadata updater setup. A null value is handled separately and produces a different message.","commonSituations":"Typo in client.rack.metadata.recovery.strategy or similar config key; passing a value valid in a newer broker version (e.g. a future strategy name) into an older client; externalized config file with stray whitespace or quotes around the value; default override left from experimentation.","solutions":["Set the property to a supported value: 'none' (default) or 'rebootstrap'.","Remove the property entirely to accept the default 'none'.","Trim/normalize whitespace and quotes in externalized config before passing to the client.","Upgrade the client to a version that supports the strategy name you intend to use."],"exampleFix":"// before\nprops.put(\"client.rack.metadata.recovery.strategy\", \"re-bootstrap\");\n// after\nprops.put(\"client.rack.metadata.recovery.strategy\", \"rebootstrap\");","handlingStrategy":"validation","validationCode":"// Validate the recovery-strategy name before calling MetadataRecoveryStrategy.forname(...)\nString name = configValue; // user-supplied\nif (name == null) {\n    throw new IllegalArgumentException(\"MetadataRecoveryStrategy name must not be null\");\n}\njava.util.Set<String> allowed = java.util.Arrays.stream(MetadataRecoveryStrategy.values())\n        .map(s -> s.name.toLowerCase(java.util.Locale.ROOT))\n        .collect(java.util.Collectors.toSet());\nif (!allowed.contains(name.toLowerCase(java.util.Locale.ROOT))) {\n    throw new IllegalArgumentException(\n        \"Invalid MetadataRecoveryStrategy '\" + name + \"'. Allowed: \" + allowed);\n}\nMetadataRecoveryStrategy strategy = MetadataRecoveryStrategy.forname(name);","typeGuard":"// Narrow an arbitrary string to a known strategy before use.\npublic static java.util.Optional<MetadataRecoveryStrategy> asStrategy(String name) {\n    if (name == null) return java.util.Optional.empty();\n    return java.util.Arrays.stream(MetadataRecoveryStrategy.values())\n            .filter(s -> s.name.equalsIgnoreCase(name))\n            .findFirst();\n}\n// Usage: asStrategy(raw).orElseThrow(() -> new IllegalArgumentException(\"bad strategy: \" + raw));","tryCatchPattern":"try {\n    MetadataRecoveryStrategy strategy = MetadataRecoveryStrategy.forname(userInput);\n} catch (IllegalArgumentException e) {\n    // surface a configuration error to the user, fall back to MetadataRecoveryStrategy.NONE,\n    // or reject the config entirely. Do not silently ignore.\n    throw new IllegalArgumentException(\"Bad client.metadata-recovery-strategy: \" + userInput, e);\n}","preventionTips":["Treat MetadataRecoveryStrategy as a closed enum: only 'none' and 'rebootstrap' are valid.","Validate user-supplied config strings against the enum's name set at config-load time, not at first use.","Use the lowercase name field (MetadataRecoveryStrategy.name) for config, never name() unless you also uppercase before lookup.","Reject null early with a clear message instead of letting forname throw an opaque one."],"tags":["config","metadata-recovery","illegal-argument","startup"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}