Tencent/matrix · warning · ParseException
cstime
Error message
${statBuffer}
cstime: ${num} What it means
Same field-wise parser as above, but for field 17 (cstime, waited-for children's system time). The parser requires the token to pass isNumeric(); otherwise it throws ParseException embedding the entire stat buffer and the offending cstime token for diagnosis.
Solutions
- Catch ParseException around parseWithBufferForPath and skip the sample.
- Inspect the message's last line (the cstime token) and the stat layout; if fields are shifted, fix field counting after '(comm)'.
- Retry the read — transient truncation during process exit is the most common cause.
- Fall back to a more tolerant parser (e.g. parseWithSplits on the raw string) or drop the metric for the affected device.
Example fix
// before
stat.cstime = MatrixUtil.parseLong(num, 0);
// after (caller side)
try {
stat = ProcStatUtil.parseWithBufferForPath(path);
} catch (ParseException e) {
MatrixLog.w(TAG, "cstime parse failed: " + e.getMessage());
stat = ProcStat.empty();
} Defensive patterns
Strategy: try-catch
Validate before calling
String raw = readProcStat(pid);
if (raw != null && raw.split("\\s+").length >= 18 && raw.split("\\s+")[17].matches("\\d+")) {
stat = ProcStatUtil.parseWithBufferForPath(path);
} Type guard
static boolean isNumericToken(String s) { return s != null && s.matches("\\d+"); } Try / catch
try {
stat = ProcStatUtil.parseWithBufferForPath(path);
} catch (ParseException e) {
Log.w(TAG, "cstime field invalid: " + e.getMessage());
stat = ProcStat.empty();
} Prevention
- Treat every /proc read as potentially partial; wrap in try-catch.
- Skip samples from threads that just exited (check /proc/<tid> existence first).
- Compare kernel stat format on failing devices before changing parser logic.
- Use fallback parseWithSplits when the buffer parser fails.
When it happens
Trigger: parseWithBuffer encounters a non-numeric token at field 17 of /proc/<pid>/stat — torn/partial buffer from a dying process, misaligned field indexing caused by odd characters in comm, or truncated reads via parseWithBufferForPath.
Common situations: Sampling threads that exit during battery canary polling; devices whose kernels emit extra/missing stat fields; reading a stale snapshot written by another tool.
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
- cutime
- 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/ecdfc09d4b11250c.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatUtil.java:277
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;
}
default:
i++;
}
}
return stat;
}
@VisibleForTesting
static ProcStat parseWithSplits(String cat) throws ParseException {
ProcStat stat = new ProcStat();
if (!TextUtils.isEmpty(cat)) {
int index = cat.indexOf(")");
if (index <= 0) throw new IllegalStateException(cat + " has not ')'");View on GitHub (pinned to 3b8293bd65)