{"record":{"id":"6b4ed7a2a0813b11","repo":"chinabugotech/hutool","slug":"invalid-number-of-x","errorCode":null,"errorMessage":"invalid number of X","messagePattern":"invalid number of X","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/date/format/FastDateParser.java","lineNumber":775,"sourceCode":"\t\tprivate static final Strategy ISO_8601_2_STRATEGY = new ISO8601TimeZoneStrategy(\"(Z|(?:[+-]\\\\d{2}\\\\d{2}))\");\n\t\tprivate static final Strategy ISO_8601_3_STRATEGY = new ISO8601TimeZoneStrategy(\"(Z|(?:[+-]\\\\d{2}(?::)\\\\d{2}))\");\n\n\t\t/**\n\t\t * Factory method for ISO8601TimeZoneStrategies.\n\t\t *\n\t\t * @param tokenLen a token indicating the length of the TimeZone String to be formatted.\n\t\t * @return a ISO8601TimeZoneStrategy that can format TimeZone String of length {@code tokenLen}. If no such strategy exists, an IllegalArgumentException will be thrown.\n\t\t */\n\t\tstatic Strategy getStrategy(final int tokenLen) {\n\t\t\tswitch (tokenLen) {\n\t\t\t\tcase 1:\n\t\t\t\t\treturn ISO_8601_1_STRATEGY;\n\t\t\t\tcase 2:\n\t\t\t\t\treturn ISO_8601_2_STRATEGY;\n\t\t\t\tcase 3:\n\t\t\t\t\treturn ISO_8601_3_STRATEGY;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new IllegalArgumentException(\"invalid number of X\");\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static final Strategy NUMBER_MONTH_STRATEGY = new NumberStrategy(Calendar.MONTH) {\n\t\t@Override\n\t\tint modify(final FastDateParser parser, final int iValue) {\n\t\t\treturn iValue - 1;\n\t\t}\n\t};\n\tprivate static final Strategy LITERAL_YEAR_STRATEGY = new NumberStrategy(Calendar.YEAR);\n\tprivate static final Strategy WEEK_OF_YEAR_STRATEGY = new NumberStrategy(Calendar.WEEK_OF_YEAR);\n\tprivate static final Strategy WEEK_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.WEEK_OF_MONTH);\n\tprivate static final Strategy DAY_OF_YEAR_STRATEGY = new NumberStrategy(Calendar.DAY_OF_YEAR);\n\tprivate static final Strategy DAY_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_MONTH);\n\tprivate static final Strategy DAY_OF_WEEK_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK) {\n\t\t@Override\n\t\tint modify(final FastDateParser parser, final int iValue) {","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateParser.java#L757-L793","documentation":"The ISO-8601 timezone token 'X' in a FastDateParser pattern only supports lengths 1, 2, or 3 (X, XX, XXX). Any other run length (e.g. XXXX or XXXXX) reaches the default branch and throws. Standard java.text.SimpleDateFormat allows 1-5 X's, so this is a reduced feature set.","triggerScenarios":"A pattern containing four or five consecutive X characters (XXXX / XXXXX), e.g. 'yyyy-MM-dd'T'HH:mm:ssXXXXX'. Lengths outside {1,2,3} are rejected at parser construction time.","commonSituations":"Patterns copied from ISO-8601 examples or RFC 3339 that use the full 5-X form (e.g. for '+hh:mm' with optional colon and 'Z'); migrating code from SimpleDateFormat to Hutool's FastDateFormat.","solutions":["Reduce the X run to at most 3 (XXX gives '+hh:mm' / 'Z').","If XXXX/XXXXX semantics are needed, use java.text.SimpleDateFormat for that format instead of FastDateParser.","Use Z or z tokens for zone formatting/parsing where appropriate."],"exampleFix":"// before\nFastDateFormat fdf = FastDateFormat.getInstance(\"yyyy-MM-dd'T'HH:mm:ssXXXXX\");\n// after\nFastDateFormat fdf = FastDateFormat.getInstance(\"yyyy-MM-dd'T'HH:mm:ssXXX\");","handlingStrategy":"validation","validationCode":"String sanitizeX(String p){ return p.replaceAll(\"X{4,}\", \"XXX\"); } // collapse long X runs\n// or reject:\nvoid assertShortX(String p){ if(p.matches(\".*X{4,5}.*\")) throw new IllegalArgumentException(\"FastDateParser supports at most XXX\"); }","typeGuard":null,"tryCatchPattern":"try { FastDateFormat.getInstance(pattern); }\ncatch (IllegalArgumentException e){ if(e.getMessage().contains(\"invalid number of X\")) { pattern = pattern.replaceAll(\"X{4,}\",\"XXX\"); } else throw e; }","preventionTips":["Prefer XXX for ISO-8601 offsets in Hutool patterns.","Document the 1-3 X limit vs java.text.SimpleDateFormat.","Validate patterns during onboarding/config load."],"tags":["date","format-pattern","timezone","iso8601","fast-date","argument"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}