Tencent/matrix · warning · ParseException
cutime
Error message
${statBuffer}
cutime: ${num} What it means
ProcStatUtil parses the kernel /proc/<pid>/stat format field-by-field; field 16 (cutime, waited-for children's user time) must be numeric. When the token read for field 16 fails isNumeric(), it throws java.text.ParseException carrying the full raw stat buffer plus the offending token, so callers can see exactly which field of the proc entry was malformed.
Solutions
- Wrap the parse call in try-catch (ParseException) and skip/retry the sample instead of crashing battery monitoring.
- Check the raw stat string in the exception message: verify field 16 (cutime) is an integer; recount fields after the '(comm)' section since spaces in comm shift the index.
- Re-read /proc/<pid>/stat fresh — a torn/truncated read is the usual cause; retry usually succeeds.
- If it reproduces on one device, dump the kernel version and compare /proc/self/stat output; consider falling back to parseWithSplits or disabling the collector on that ROM.
Example fix
// before
ProcStat stat = ProcStatUtil.parseWithBufferForPath(path);
// after
ProcStat stat;
try {
stat = ProcStatUtil.parseWithBufferForPath(path);
} catch (ParseException e) {
MatrixLog.w(TAG, "bad stat: " + e.getMessage());
stat = null; // skip this sample
} Defensive patterns
Strategy: try-catch
Validate before calling
String raw = readProcStat(pid);
if (raw != null && raw.contains(")") && raw.split("\\s+").length >= 22) {
stat = ProcStatUtil.parseWithBufferForPath(path);
} Type guard
static boolean looksLikeValidStat(String raw) {
if (raw == null || raw.indexOf(')') < 0) return false;
String[] parts = raw.split("\\s+");
return parts.length >= 22 && parts[16].matches("\\d+") && parts[17].matches("\\d+");
} Try / catch
try {
stat = ProcStatUtil.parseWithBufferForPath(path);
} catch (ParseException e) {
Log.w(TAG, "stat parse failed, skipping sample: " + e.getMessage());
stat = null;
} Prevention
- Always catch ParseException around /proc stat parsing — files can be torn when processes exit.
- Re-read rather than fail on first error; transient truncation is common under process churn.
- Log the raw stat line from the exception message for device-specific format debugging.
- Field positions shift if comm contains spaces — count from after the ')' character.
When it happens
Trigger: Calling ProcStatUtil.parseWithBuffer (via parseWithBufferForPath) on a /proc stat byte buffer whose field 16 does not parse as a number — e.g. truncated/partial read of /proc/<tid>/stat, a process exiting mid-read leaving a torn line, or kernel/vendor formats that shift field positions (comm containing unexpected bytes breaking field indexing).
Common situations: Reading stat of a thread/process that dies between open and read on a heavily loaded device; OEM kernels with modified /proc formatting; parsing stale buffers captured at app start when the process table is churning.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- cstime
- ProcStatReader error
- Matrix init, Matrix should not be null.
- you must init Matrix sdk first
- matrix init, application is null
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/4a693ef079b5652e.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatUtil.java:263
window++;
}
String num = safeBytesToString(statBuffer, readIdx, window);
if (!isNumeric(num)) {
throw new ParseException(safeBytesToString(statBuffer, 0, statBuffer.length) + "\nstime: " + num);
}
stat.stime = MatrixUtil.parseLong(num, 0);
break;
}
case 16: { // cutime
int readIdx = i, window = 0;
// seek next space
while (i < statBytes && !Character.isSpaceChar(statBuffer[i])) {
i++;
window++;
}
String num = safeBytesToString(statBuffer, readIdx, window);
if (!isNumeric(num)) {
throw new ParseException(safeBytesToString(statBuffer, 0, statBuffer.length) + "\ncutime: " + num);
}
stat.cutime = MatrixUtil.parseLong(num, 0);
break;
}
case 17: { // cstime
int readIdx = i, window = 0;
// seek next space
while (i < statBytes && !Character.isSpaceChar(statBuffer[i])) {
i++;
window++;
}
String num = safeBytesToString(statBuffer, readIdx, window);
if (!isNumeric(num)) {
throw new ParseException(safeBytesToString(statBuffer, 0, statBuffer.length) + "\ncstime: " + num);
}
stat.cstime = MatrixUtil.parseLong(num, 0);
break;
}View on GitHub (pinned to 3b8293bd65)