{"record":{"id":"4e0740dbaeb2eb2e","repo":"jwtk/jjwt","slug":"locale-part-contains-invalid-characters","errorCode":null,"errorMessage":"Locale part \"\" contains invalid characters","messagePattern":"Locale part \"\" contains invalid characters","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/jsonwebtoken/lang/Strings.java","lineNumber":874,"sourceCode":"        String variant = \"\";\n        if (parts.length >= 2) {\n            // There is definitely a variant, and it is everything after the country\n            // code sans the separator between the country code and the variant.\n            int endIndexOfCountryCode = localeString.indexOf(country) + country.length();\n            // Strip off any leading '_' and whitespace, what's left is the variant.\n            variant = trimLeadingWhitespace(localeString.substring(endIndexOfCountryCode));\n            if (variant.startsWith(\"_\")) {\n                variant = trimLeadingCharacter(variant, '_');\n            }\n        }\n        return (language.length() > 0 ? new Locale(language, country, variant) : null);\n    }\n\n    private static void validateLocalePart(String localePart) {\n        for (int i = 0; i < localePart.length(); i++) {\n            char ch = localePart.charAt(i);\n            if (ch != '_' && ch != ' ' && !Character.isLetterOrDigit(ch)) {\n                throw new IllegalArgumentException(\"Locale part \\\"\" + localePart + \"\\\" contains invalid characters\");\n            }\n        }\n    }\n\n    /**\n     * Determine the RFC 3066 compliant language tag,\n     * as used for the HTTP \"Accept-Language\" header.\n     *\n     * @param locale the Locale to transform to a language tag\n     * @return the RFC 3066 compliant language tag as String\n     */\n    public static String toLanguageTag(Locale locale) {\n        return locale.getLanguage() + (hasText(locale.getCountry()) ? \"-\" + locale.getCountry() : \"\");\n    }\n\n\n    //---------------------------------------------------------------------\n    // Convenience methods for working with String arrays","sourceCodeStart":856,"sourceCodeEnd":892,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/api/src/main/java/io/jsonwebtoken/lang/Strings.java#L856-L892","documentation":"Thrown by Strings.validateLocalePart when a component of a locale string (language, country, or variant) contains characters other than letters, digits, underscore, or space. JJWT validates locale parts before constructing a java.util.Locale to reject malformed values early.","triggerScenarios":"Calling a JJWT API that takes a locale string (e.g. in builders for locale-aware claims or Locale strings) with a part containing characters like '-', '#', '.', or other punctuation.","commonSituations":"Passing BCP-47 style tags with hyphens (\"en-US\") where underscore form is expected, or locale strings polluted by config file syntax or URL encoding.","solutions":["Remove invalid characters from the locale part; use only letters, digits, '_' and ' '","Split combined tags into language/country/variant parts and pass each part separately","Replace hyphens with underscores if converting from BCP-47: \"en-US\" -> \"en_US\"","Catch IllegalArgumentException and fall back to a default Locale"],"exampleFix":"// before\nLocale locale = new Locale(\"en-US\"); // hyphen rejected\n// after\nLocale locale = Locale.forLanguageTag(\"en-US\"); // or new Locale(\"en\", \"US\")","handlingStrategy":"validation","validationCode":"String part = localePart == null ? \"\" : localePart;\nfor (char ch : part.toCharArray()) {\n    if (ch != '_' && ch != ' ' && !Character.isLetterOrDigit(ch)) throw new IllegalArgumentException(\"Invalid locale char: \" + ch);\n}","typeGuard":null,"tryCatchPattern":"try {\n    locale = buildLocale(raw);\n} catch (IllegalArgumentException e) {\n    locale = Locale.ROOT; // safe default\n}","preventionTips":["Use Locale.forLanguageTag for BCP-47 tags with hyphens instead of splitting manually","Normalize \"-\" to \"_\" when converting between formats","Restrict locale config inputs to [A-Za-z0-9_ ] with a regex at config load time"],"tags":["java","locale","format-validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}