{"record":{"id":"ecdfc09d4b11250c","repo":"Tencent/matrix","slug":"statbuffer-cstime-num","errorCode":null,"errorMessage":"${statBuffer}\ncstime: ${num}","messagePattern":"(.+?)\ncstime: (.+?)","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"warning","filePath":"matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatUtil.java","lineNumber":277,"sourceCode":"                        window++;\n                    }\n                    String num = safeBytesToString(statBuffer, readIdx, window);\n                    if (!isNumeric(num)) {\n                        throw new ParseException(safeBytesToString(statBuffer, 0, statBuffer.length) + \"\\ncutime: \" + num);\n                    }\n                    stat.cutime = MatrixUtil.parseLong(num, 0);\n                    break;\n                }\n                case 17: { // cstime\n                    int readIdx = i, window = 0;\n                    // seek next space\n                    while (i < statBytes && !Character.isSpaceChar(statBuffer[i])) {\n                        i++;\n                        window++;\n                    }\n                    String num = safeBytesToString(statBuffer, readIdx, window);\n                    if (!isNumeric(num)) {\n                        throw new ParseException(safeBytesToString(statBuffer, 0, statBuffer.length) + \"\\ncstime: \" + num);\n                    }\n                    stat.cstime = MatrixUtil.parseLong(num, 0);\n                    break;\n                }\n\n                default:\n                    i++;\n            }\n        }\n        return stat;\n    }\n\n    @VisibleForTesting\n    static ProcStat parseWithSplits(String cat) throws ParseException {\n        ProcStat stat = new ProcStat();\n        if (!TextUtils.isEmpty(cat)) {\n            int index = cat.indexOf(\")\");\n            if (index <= 0) throw new IllegalStateException(cat + \" has not ')'\");","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatUtil.java#L259-L295","documentation":"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.","triggerScenarios":"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.","commonSituations":"Sampling threads that exit during battery canary polling; devices whose kernels emit extra/missing stat fields; reading a stale snapshot written by another tool.","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."],"exampleFix":"// before\nstat.cstime = MatrixUtil.parseLong(num, 0);\n// after (caller side)\ntry {\n    stat = ProcStatUtil.parseWithBufferForPath(path);\n} catch (ParseException e) {\n    MatrixLog.w(TAG, \"cstime parse failed: \" + e.getMessage());\n    stat = ProcStat.empty();\n}","handlingStrategy":"try-catch","validationCode":"String raw = readProcStat(pid);\nif (raw != null && raw.split(\"\\\\s+\").length >= 18 && raw.split(\"\\\\s+\")[17].matches(\"\\\\d+\")) {\n    stat = ProcStatUtil.parseWithBufferForPath(path);\n}","typeGuard":"static boolean isNumericToken(String s) { return s != null && s.matches(\"\\\\d+\"); }","tryCatchPattern":"try {\n    stat = ProcStatUtil.parseWithBufferForPath(path);\n} catch (ParseException e) {\n    Log.w(TAG, \"cstime field invalid: \" + e.getMessage());\n    stat = ProcStat.empty();\n}","preventionTips":["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."],"tags":["android","procfs","parse","battery-monitoring"],"backgroundTag":"invalid-argument-format","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}