Tencent/QMUI_Android · error · IllegalArgumentException
end must > start
Error message
end must > start
What it means
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.
Source
Thrown at qmui/src/main/java/com/qmuiteam/qmui/qqface/QMUIQQFaceCompiler.java:100
if (QMUILangHelper.isNullOrEmpty(text)) {
return null;
}
return compile(text, 0, text.length());
}
public ElementList compile(CharSequence text, int start, int end) {
return compile(text, start, end, false);
}
private ElementList compile(CharSequence text, int start, int end, boolean inSpan) {
if (QMUILangHelper.isNullOrEmpty(text)) {
return null;
}
if (start < 0 || start >= text.length()) {
throw new IllegalArgumentException("start must >= 0 and < text.length");
}
if (end <= start) {
throw new IllegalArgumentException("end must > start");
}
int size = text.length();
if (end > size) {
end = size;
}
boolean hasClickableSpans = false;
QMUITouchableSpan[] spans = null;
int[] spanInfo = null;
if (!inSpan && (text instanceof Spannable)) {
final Spannable spannable = (Spannable) text;
spans = ((Spannable) text).getSpans(
0,
text.length() - 1,
QMUITouchableSpan.class);
Arrays.sort(spans, new Comparator<QMUITouchableSpan>() {
@OverrideView on GitHub (pinned to 026e7d4866)
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).
Example fix
// before
int spanEnd = spannable.getSpanEnd(span);
compiler.compile(text, start, spanEnd, true); // spanEnd may be <= start
// after
int spanEnd = spannable.getSpanEnd(span);
if (spanEnd > start) {
compiler.compile(text, start, spanEnd, true);
} Defensive patterns
Strategy: validation
Validate before calling
if (end > start) {
compiler.compile(text, start, end, inSpan);
} Type guard
boolean isRangeValid(CharSequence text, int start, int end) {
return start >= 0 && end > start && start < text.length();
} Try / catch
try {
compiler.compile(text, start, end, true);
} catch (IllegalArgumentException e) {
Log.w(TAG, "invalid span range " + start + ".." + end, e);
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Measuring a touch span over text that was mutated after compilation, or computing end as start + 0 for an empty/deleted span region.
Related errors
- start must >= 0 and < text.length
- mCompiler == null
- index must greater than 0
- Not support the type: %s
- topView must implement from IQMUIContinuousNestedTopView
AI-assisted analysis of Tencent/QMUI_Android@026e7d4866 (2026-09-06).
Data as JSON: /api/errors/b00596af1316975c.
Report an issue: GitHub.