{"record":{"id":"6d4ce56ca3182947","repo":"hibernate/hibernate-orm","slug":"invalid-script-s","errorCode":null,"errorMessage":"Invalid script: %s","messagePattern":"Invalid script: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleJavaType.java","lineNumber":138,"sourceCode":"\t\t\t\tcase VARIANT -> {\n\t\t\t\t\tif ( chars[start] == '#' ) {\n\t\t\t\t\t\tif ( isScript( chars, start + 1, length - 1 ) ) {\n\t\t\t\t\t\t\tbuilder.setScript( new String( chars, start + 1, length - 1 ) );\n\t\t\t\t\t\t\tyield EXTENSION;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\thandleExtension( chars, start + 1, length - 1, builder );\n\t\t\t\t\t\t\tyield END;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tbuilder.setVariant( new String( chars, start, length ) );\n\t\t\t\t\t\tyield SCRIPT;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcase SCRIPT -> {\n\t\t\t\t\tif ( length < 5 || chars[start] != '#' ) {\n\t\t\t\t\t\tthrow new IllegalArgumentException( \"Invalid script: \" + new String( chars, start, length ) );\n\t\t\t\t\t}\n\t\t\t\t\tif ( isScript( chars, start + 1, length - 1 ) ) {\n\t\t\t\t\t\tbuilder.setScript( new String( chars, start + 1, length - 1 ) );\n\t\t\t\t\t\tyield EXTENSION;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\thandleExtension( chars, start + 1, length - 1, builder );\n\t\t\t\t\t\tyield END;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcase EXTENSION -> {\n\t\t\t\t\thandleExtension(  chars, start, length, builder );\n\t\t\t\t\tyield END;\n\t\t\t\t}\n\t\t\t\tcase END -> throw new IllegalStateException( \"Unexpected continuation of locale value after extension: \" + new String( chars, start, length ) );\n\t\t\t};\n\t\t}\n","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocaleJavaType.java#L120-L156","documentation":"LocaleJavaType.fromString() parses legacy underscore-separated locale values with a small state machine: language_region_variant#Script_extension. After a variant segment was read (state SCRIPT), the next underscore-separated segment must start with '#' and be at least 5 characters ('#Latn'); the 4 characters after '#' must be letters to count as a script, otherwise the code falls through to extension handling. A segment that is shorter than 5 chars or does not start with '#' throws IllegalArgumentException(\"Invalid script: ...\").","triggerScenarios":"A stored locale value with a fourth underscore segment lacking '#', e.g. 'en_US_some_variant_x'; a '#'-segment shorter than 5 characters, e.g. 'en_US_var#Lat'; malformed script casing/length like 'en_US_var#Latin' (5 letters, so treated as extension and rejected there)","commonSituations":"User-profile locale strings ingested from external systems into a Locale-mapped column; teams writing BCP 47 tags ('zh-Hans-CN') but replacing '-' with '_' before storing; concatenating extra keys to locale codes ('en_US_default').","solutions":["Store BCP 47 language tags instead: the parser detects '-' during the language segment and delegates to Locale.Builder.setLanguageTag, which is far more tolerant","Keep legacy values in the exact grammar language_region_variant#Script (script exactly 4 letters, '#' prefix)","Validate and normalize locale strings before persisting: Locale.forLanguageTag(s) then toLanguageTag()","Clean existing rows that carry trailing underscore segments or malformed '#script' parts"],"exampleFix":"// before\nString locale = \"en_US_default_variant\"; // stored in Locale column -> Invalid script: default\n\n// after\nString locale = \"en-US\"; // BCP 47 tag, parsed via setLanguageTag\n// or legacy form: \"en_US_default#Latn\"","handlingStrategy":"validation","validationCode":"static boolean isValidHibernateLocale(String s) {\n    if (s == null || s.isEmpty()) return true; // empty -> Locale.ROOT\n    try {\n        org.hibernate.type.descriptor.java.LocaleJavaType.INSTANCE.fromString(s);\n        return true;\n    } catch (RuntimeException e) { return false; }\n}\n\n// at the write boundary:\nif (!isValidHibernateLocale(input)) reject(input);","typeGuard":"static java.util.Locale tryLocale(String s) {\n    try { return java.util.Locale.forLanguageTag(s.replace('_','-')); }\n    catch (Exception e) { return null; }\n}","tryCatchPattern":"catch (IllegalArgumentException e) {\n    // message starts with \"Invalid script: \"\n    throw new IllegalArgumentException(\"Locale must be 'lang_REGION_variant#Script_ext' or a BCP 47 tag: \" + value, e);\n}","preventionTips":["Store BCP 47 language tags ('en-US'); Hibernate routes them through setLanguageTag","Keep legacy values in grammar order language_region_variant#Script (script exactly 4 letters after '#')","Normalize with Locale.forLanguageTag(...).toLanguageTag() before persisting user input"],"tags":["hibernate","locale","parsing","legacy-locale-format","illegalargumentexception"],"backgroundTag":"invalid-locale-format","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}