{"record":{"id":"d9526375886bd45e","repo":"Tencent/QMUI_Android","slug":"start-must-0-and-text-length","errorCode":null,"errorMessage":"start must >= 0 and < text.length","messagePattern":"start must >= 0 and < text\\.length","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"qmui/src/main/java/com/qmuiteam/qmui/qqface/QMUIQQFaceCompiler.java","lineNumber":97,"sourceCode":"    }\n\n    public ElementList compile(CharSequence text) {\n        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,","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/qmui/src/main/java/com/qmuiteam/qmui/qqface/QMUIQQFaceCompiler.java#L79-L115","documentation":"The private ElementList compile(CharSequence, int, int, boolean) in QMUIQQFaceCompiler validates the substring bounds before parsing text for QQ face codes. If start is negative or past the end of the text, no valid element can be produced and an IllegalArgumentException is thrown. It is invoked recursively while scanning text and from createTouchSpanElement when measuring touch spans.","triggerScenarios":"Calling the public compile(text)/compile(text, start) with a negative start or start >= text.length(); internal recursion computing a bad start (e.g. from a Span whose offsets are inconsistent with the text, such as after mutating text without recompiling).","commonSituations":"Passing an empty CharSequence to an overload without the isNullOrEmpty guard, computing span offsets against stale text, or misusing the public start-offset overload with an offset beyond the string.","solutions":["Clamp/validate start before calling: ensure 0 <= start && start < text.length().","If using an offset derived from a Spannable, verify it was computed against the current text, and recompile after text changes.","Check the public entry points (compile(text) etc.) — if text can be empty, guard with QMUILangHelper.isNullOrEmpty before calling.","Report/log if internal createTouchSpanElement produces out-of-range offsets; usually means the Spannable was modified after compilation."],"exampleFix":"// before\ncompiler.compile(text, someOffset); // someOffset may equal text.length()\n\n// after\nif (someOffset >= 0 && someOffset < text.length()) {\n    compiler.compile(text, someOffset);\n}","handlingStrategy":"validation","validationCode":"if (text != null && start >= 0 && start < text.length()) {\n    compiler.compile(text, start);\n}","typeGuard":"boolean canCompile(CharSequence text, int start) {\n    return text != null && !text.toString().isEmpty()\n        && start >= 0 && start < text.length();\n}","tryCatchPattern":"try {\n    compiler.compile(text, start);\n} catch (IllegalArgumentException e) {\n    Log.w(TAG, \"invalid compile range: \" + start, e);\n}","preventionTips":["Validate offsets before slicing text","Recompile after any Spannable/text mutation","Guard empty text before calling compile overloads with offsets"],"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"}