{"id":"642d53e9b21a1585","repo":"apache/kafka","slug":"string-must-be-one-of-string-join-validstri","errorCode":null,"errorMessage":"String must be one of: String.join(\", \", validStrings)","messagePattern":"String must be one of: String\\.join\\(\", \", validStrings\\)","errorType":"validation","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java","lineNumber":1116,"sourceCode":"        }\n    }\n\n    public static class ValidString implements Validator {\n        final List<String> validStrings;\n\n        private ValidString(List<String> validStrings) {\n            this.validStrings = validStrings;\n        }\n\n        public static ValidString in(String... validStrings) {\n            return new ValidString(Arrays.asList(validStrings));\n        }\n\n        @Override\n        public void ensureValid(String name, Object o) {\n            String s = (String) o;\n            if (!validStrings.contains(s)) {\n                throw new ConfigException(name, o, \"String must be one of: \" + String.join(\", \", validStrings));\n            }\n\n        }\n\n        public String toString() {\n            return \"[\" + String.join(\", \", validStrings) + \"]\";\n        }\n    }\n\n    public static class CaseInsensitiveValidString implements Validator {\n\n        final Set<String> validStrings;\n\n        private CaseInsensitiveValidString(List<String> validStrings) {\n            this.validStrings = validStrings.stream()\n                .map(s -> s.toUpperCase(Locale.ROOT))\n                .collect(Collectors.toSet());\n        }","sourceCodeStart":1098,"sourceCodeEnd":1134,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java#L1098-L1134","documentation":"Thrown by ValidString.ensureValid when the supplied string is not a member of the validator's enumerated validStrings list (case-sensitive exact match via List.contains). ConfigDef uses ValidString.in(...) to constrain a config to a closed set of allowed values (e.g. an enum-like option); the message lists every permitted value to aid correction.","triggerScenarios":"A ConfigKey validated with ValidString.in(\"read\",\"write\",\"admin\") is given a value not in that set, e.g. \"READ\" (wrong case) or \"superuser\". Triggered during ConfigDef.parse()/validate() when the validator's ensureValid runs.","commonSituations":"Wrong casing of an allowed value (\"READ\" vs \"read\"), typo in the config, using a value valid in an older/newer Kafka version that has since been renamed or removed, or copy-pasting a value from documentation for a different component.","solutions":["Set the config to one of the values literally printed in the message, observing exact case.","If you need case-insensitive matching, change the ConfigKey validator to CaseInsensitiveValidString.in(...) (requires the config's owner module to support it).","Check the Kafka version of your client/broker docs for the canonical list of allowed values — the set may differ across versions."],"exampleFix":"// before\nprops.put(\"security.protocol\", \"TLS\");  // not in valid set\n\n// after\nprops.put(\"security.protocol\", \"SSL\");","handlingStrategy":"validation","validationCode":"// Validate against the same allow-list Kafka's ValidString uses:\nSet<String> allowed = Set.of(\"PLAIN\", \"SCRAM-SHA-512\", \"GSSAPI\", \"OAUTHBEARER\"); // example: sasl.mechanism\nString val = (String) configs.getOrDefault(\"sasl.mechanism\", \"\");\nif (!allowed.contains(val)) {\n    throw new IllegalArgumentException(\"sasl.mechanism must be one of \" + allowed + \" but was '\" + val + \"'\");\n}","typeGuard":"// Narrow to a known enum-like constant at the boundary:\nenum SaslMechanism { PLAIN, SCRAM_SHA_512, GSSAPI, OAUTHBEARER; }","tryCatchPattern":"try {\n    def.parse(props);\n} catch (ConfigException ce) {\n    if (ce.getMessage().startsWith(\"String must be one of:\")) {\n        log.error(\"Config '{}' has illegal value '{}'. Allowed: {}\",\n                  ce.getName(), ce.value(), ce.getMessage());\n        promptOperatorFor(ce.getName());\n    } else throw ce;\n}","preventionTips":["Keep the allow-list in one place (an enum) and drive both UI dropdowns and config validation from it.","Log the full ce.getMessage() on failure — it prints the valid values verbatim.","Add a CI check that compares your supplied enum values against the ones Kafka's ConfigDef advertises."],"tags":["config","kafka-client","validation","validator","enum"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}