{"record":{"id":"b00596af1316975c","repo":"Tencent/QMUI_Android","slug":"end-must-start","errorCode":null,"errorMessage":"end must > start","messagePattern":"end must > start","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"qmui/src/main/java/com/qmuiteam/qmui/qqface/QMUIQQFaceCompiler.java","lineNumber":100,"sourceCode":"        if (QMUILangHelper.isNullOrEmpty(text)) {\n            return null;\n        }\n        return compile(text, 0, text.length());\n    }\n\n    public ElementList compile(CharSequence text, int start, int end) {\n        return compile(text, start, end, false);\n    }\n\n    private ElementList compile(CharSequence text, int start, int end, boolean inSpan) {\n        if (QMUILangHelper.isNullOrEmpty(text)) {\n            return null;\n        }\n        if (start < 0 || start >= text.length()) {\n            throw new IllegalArgumentException(\"start must >= 0 and < text.length\");\n        }\n        if (end <= start) {\n            throw new IllegalArgumentException(\"end must > start\");\n        }\n        int size = text.length();\n\n        if (end > size) {\n            end = size;\n        }\n\n        boolean hasClickableSpans = false;\n        QMUITouchableSpan[] spans = null;\n        int[] spanInfo = null;\n        if (!inSpan && (text instanceof Spannable)) {\n            final Spannable spannable = (Spannable) text;\n            spans = ((Spannable) text).getSpans(\n                    0,\n                    text.length() - 1,\n                    QMUITouchableSpan.class);\n            Arrays.sort(spans, new Comparator<QMUITouchableSpan>() {\n                @Override","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/qmui/src/main/java/com/qmuiteam/qmui/qqface/QMUIQQFaceCompiler.java#L82-L118","documentation":"QMUIQQFaceCompiler.compile() requires end > start when slicing the CharSequence; passing end <= start is rejected with an IllegalArgumentException. Note that end larger than text length is tolerated (clamped to size), so the error only fires for end <= start.","triggerScenarios":"Calling a compile overload with an explicit end that is <= start; span offsets (getSpanStart/getSpanEnd) inverted because the Spannable was edited after spans were computed; recursion passing a zero-length range.","commonSituations":"Measuring a touch span over text that was mutated after compilation, or computing end as start + 0 for an empty/deleted span region.","solutions":["Ensure end > start before invoking; skip empty ranges instead of compiling them.","Recompile the QMUIQQFaceView after any text/Spannable mutation so offsets stay consistent.","Validate span boundaries: only call createTouchSpanElement/compile when spanEnd > spanStart.","Clamp end to text.length() yourself if unsure — values greater than length are safe (they get clamped internally)."],"exampleFix":"// before\nint spanEnd = spannable.getSpanEnd(span);\ncompiler.compile(text, start, spanEnd, true); // spanEnd may be <= start\n\n// after\nint spanEnd = spannable.getSpanEnd(span);\nif (spanEnd > start) {\n    compiler.compile(text, start, spanEnd, true);\n}","handlingStrategy":"validation","validationCode":"if (end > start) {\n    compiler.compile(text, start, end, inSpan);\n}","typeGuard":"boolean isRangeValid(CharSequence text, int start, int end) {\n    return start >= 0 && end > start && start < text.length();\n}","tryCatchPattern":"try {\n    compiler.compile(text, start, end, true);\n} catch (IllegalArgumentException e) {\n    Log.w(TAG, \"invalid span range \" + start + \"..\" + end, e);\n}","preventionTips":["Skip zero-length or inverted ranges before compiling","Keep span offsets in sync by recompiling after text edits","Remember end may exceed text length (it is clamped), only end <= start throws"],"tags":["android","qmui","qqface","argument-out-of-range","text-parsing"],"backgroundTag":"argument-out-of-range","analyzedSha":"026e7d486677d6593a96689cd590ec3561176717","analyzedAt":"2026-09-06T13:32:24.816Z","contentChangedAt":"2026-09-06T13:32:24.816Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}