{"record":{"id":"da50fc3ec8292461","repo":"alibaba/canal","slug":"parseinterval-failed-due-to-wrong-format-s","errorCode":null,"errorMessage":"parseInterval failed due to wrong format: %s","messagePattern":"parseInterval failed due to wrong format: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/packets/UUIDSet.java","lineNumber":161,"sourceCode":"     *\n     * @param str\n     * @return\n     */\n    public static Interval parseInterval(String str) {\n        String[] ss = str.split(\"-\");\n\n        Interval interval = new Interval();\n        switch (ss.length) {\n            case 1:\n                interval.start = Long.parseLong(ss[0]);\n                interval.stop = interval.start + 1;\n                break;\n            case 2:\n                interval.start = Long.parseLong(ss[0]);\n                interval.stop = Long.parseLong(ss[1]) + 1;\n                break;\n            default:\n                throw new RuntimeException(String.format(\"parseInterval failed due to wrong format: %s\", str));\n        }\n\n        return interval;\n    }\n\n    /**\n     * 把{start,stop}连续的合并掉: [{start:1, stop:4},{start:4, stop:5}] => [{start:1,\n     * stop:5}]\n     *\n     * @param intervals\n     * @return\n     */\n    public static List<Interval> combine(List<Interval> intervals) {\n        List<Interval> combined = new ArrayList<>();\n        Collections.sort(intervals);\n        int len = intervals.size();\n        for (int i = 0; i < len; i++) {\n            combined.add(intervals.get(i));","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/packets/UUIDSet.java#L143-L179","documentation":"Thrown by UUIDSet.parseInterval(String) when an interval segment splits into more than two pieces on '-'. Valid intervals are either a single number '5' (open-ended, start..start+1) or a closed range '1-3'. More than one '-' (e.g. '1-3-5') or a leading/trailing '-' producing empty tokens falls into the default switch case. Note the format uses inclusive bounds in the string but a half-open [start, stop) internally.","triggerScenarios":"Calling parseInterval on a substring containing '1-3-5', a negative-looking value, or a value with stray dashes. Indirectly triggered from UUIDSet.parse when any interval token after the UUID is malformed, e.g. 'UUID:1-3:bad-interval'.","commonSituations":"Hand-edited GTID intervals; a monitoring/serialization tool that joined ranges with extra dashes; version where MySQL emits an interval representation the parser does not yet handle; copy-paste of a hyphenated comment into the GTID field.","solutions":["Verify each interval token is either 'N' or 'N-M' (two non-negative integers, one optional dash) before parsing.","Sanitize the token: strip non-numeric characters except a single internal dash.","Log the offending token from UUIDSet.parse to localize which interval failed.","If you control the producer, emit canonical GTID ranges only."],"exampleFix":"// before\nUUIDSet.parse(\"726757ad-4455-11e8-ae04-0242ac110002:1-3-5\");\n\n// after\nprivate static boolean validInterval(String tok) {\n    return tok.matches(\"\\\\d+(-\\\\d+)?\");\n}\nString[] parts = gtidStr.split(\":\");\nfor (int i = 1; i < parts.length; i++) {\n    if (!validInterval(parts[i])) throw new IllegalArgumentException(\"Bad interval: \" + parts[i]);\n}","handlingStrategy":"validation","validationCode":"private static final java.util.regex.Pattern INTERVAL = java.util.regex.Pattern.compile(\"^\\\\d+(-\\\\d+)?$\");\npublic static boolean isValidInterval(String tok) { return tok != null && INTERVAL.matcher(tok).matches(); }","typeGuard":"public static boolean isParsableInterval(String s) {\n    if (s == null) return false;\n    String[] ss = s.split(\"-\");\n    if (ss.length < 1 || ss.length > 2) return false;\n    try { for (String t : ss) Long.parseLong(t); return true; }\n    catch (NumberFormatException e) { return false; }\n}","tryCatchPattern":"try {\n    UUIDSet.Interval iv = UUIDSet.parseInterval(tok);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"parseInterval failed\")) { /* reject token */ }\n    throw e;\n}","preventionTips":["Validate each interval token as 'N' or 'N-M' before calling parseInterval.","Sanitize producer output that joins ranges with extra dashes.","Unit-test the parser against canonical MySQL GTID samples."],"tags":["parsing","gtid","mysql","validation","runtime-exception"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}