Tencent/matrix · warning · ProcStatUtil.ParseException

Couldn't read string because file ended!

Error message

Couldn't read string because file ended!

What it means

ProcStatReader.readWord() throws ParseException("Couldn't read string because file ended!") when the loop finished without consuming any character (isFirstRun still true), i.e. EOF was reached before any word character. It means the stat stream ended earlier than the parser expected.

Solutions

  1. Check the process is alive before reading, or treat ParseException at EOF as 'process exited' and stop sampling that pid.
  2. Catch ParseException and skip the tick; re-open the file on the next sample.
  3. Reduce time between process enumeration and stat read to shrink the race window.
  4. Validate the stat file is non-empty before parsing (file length > 0).

Example fix

// before
StatModel stat = ProcStatUtil.instance.parse(pid);
// after
try {
    StatModel stat = ProcStatUtil.instance.parse(pid);
} catch (ProcStatUtil.ParseException e) {
    Log.w(TAG, "stat read failed (process likely exited): " + e.getMessage());
}
Defensive patterns

Strategy: retry

Validate before calling

java.io.File f = new File("/proc/" + pid + "/stat");
boolean readable = f.exists() && f.length() > 0;

Try / catch

try { ... } catch (ProcStatUtil.ParseException e) { if (e.getMessage().contains("file ended")) { /* mark pid dead */ } }

Prevention

When it happens

Trigger: Calling state()/readWord at (or after) the end of /proc/<pid>/stat - typically when the process died mid-read, truncating the file, or when the reader was already exhausted by previous field reads.

Common situations: Process termination while the battery canary walks the stat fields; a truncated or empty stat file on some devices/emulators.

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/1af33ef850896007. Report an issue: GitHub.

Appendix: source

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

                    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;
        long result = 0;
        boolean isFirstRun = true;

        while (hasNext()) {
            next();
            if (Character.isDigit(mChar)) {
                result = result * 10 + (mChar - '0');
            } else if (isFirstRun) {
                if (mChar == '-') {
                    sign = -1;

View on GitHub (pinned to 3b8293bd65)