Tencent/matrix · error · ProcStatUtil.ParseException

Couldn't read string!

Error message

Couldn't read string!

What it means

ProcStatReader.readWord() builds a whitespace-delimited token; if the very first character it reads is not a valid word character it cannot form any token and throws ParseException("Couldn't read string!"). This means the lexer found an unexpected character where a token was expected.

Solutions

  1. Catch ParseException in the caller and skip this sample tick; proc stat anomalies are usually transient.
  2. Inspect the actual /proc/<pid>/stat content on the failing device and validate it before parsing.
  3. Switch to ProcStatUtil.parseWithBuffer (byte-buffer based) which handles the parenthesized comm field differently.
  4. Retry on the next poll; a republished process or new tick typically parses fine.

Example fix

// before
CharBuffer word = reader.state();
// after
CharBuffer word;
try {
    word = reader.state();
} catch (ProcStatUtil.ParseException e) {
    return null; // skip malformed stat sample
}
Defensive patterns

Strategy: try-catch

Validate before calling

byte[] head = readFirstBytes("/proc/" + pid + "/stat", 64);
if (head == null || head.length == 0) { /* skip pid */ }

Try / catch

try { CharBuffer w = reader.state(); } catch (ProcStatUtil.ParseException e) { return null; }

Prevention

When it happens

Trigger: Calling state() (which uses readWord) when the current stream position starts on a character that fails the word-character predicate on the first iteration (isFirstRun).

Common situations: Peculiar /proc stat formatting on some kernels or emulators where the expected field is missing, empty, or preceded by unexpected characters; misaligned field offsets after a prior parse error.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/008d852d7a2aed3e. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatReader.java:145

    public CharBuffer readWord(CharBuffer buffer) {
        buffer.clear();

        boolean isFirstRun = true;

        while (hasNext()) {
            next();
            if (!Character.isWhitespace(mChar)) {
                if (!buffer.hasRemaining()) {
                    CharBuffer newBuffer = CharBuffer.allocate(buffer.capacity() * 2);
                    buffer.flip();
                    newBuffer.put(buffer);
                    buffer = newBuffer;
                }

                buffer.put(mChar);
            } else if (isFirstRun) {
                throw new ParseException("Couldn't read string!");
            } else {
                rewind();
                break;
            }

            isFirstRun = false;
        }

        if (isFirstRun) {
            throw new ParseException("Couldn't read string because file ended!");
        }

        buffer.flip();
        return buffer;
    }

    public long readNumber() {
        long sign = 1;

View on GitHub (pinned to 3b8293bd65)