{"record":{"id":"1d215e01bb1a2778","repo":"Tencent/matrix","slug":"raf-err-ioe-getmessage","errorCode":null,"errorMessage":"RAF err: ${ioe.getMessage()}","messagePattern":"RAF err: (.+?)","errorType":"exception","errorClass":"ProcStatUtil.ParseException","httpStatus":null,"severity":"warning","filePath":"matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatReader.java","lineNumber":60,"sourceCode":"        mIsValid = true;\n\n        // First, try to move the pointer if a file exists\n        if (mFile != null) {\n            try {\n                mFile.seek(0);\n            } catch (IOException ioe) {\n                close();\n            }\n        }\n\n        // Otherwise try to open/reopen the file and fail\n        if (mFile == null) {\n            try {\n                mFile = new RandomAccessFile(mPath, \"r\");\n            } catch (IOException ioe) {\n                mIsValid = false;\n                close();\n                throw new ProcStatUtil.ParseException(\"RAF err: \" + ioe.getMessage());\n            }\n        }\n\n        if (mIsValid) {\n            mPosition = -1;\n            mBufferSize = 0;\n\n            mChar = 0;\n            mPrev = 0;\n\n            mRewound = false;\n        }\n\n        return this;\n    }\n\n    public boolean isValid() {\n        return mIsValid;","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-battery-canary/src/main/java/com/tencent/matrix/batterycanary/utils/ProcStatReader.java#L42-L78","documentation":"ProcStatReader.reset() lazily opens /proc/<pid>/stat as a RandomAccessFile; if the open throws IOException the reader marks itself invalid, closes, and rethrows as ParseException(\"RAF err: <message>\"). It signals that the proc stat file could not be opened for reading at all, before any parsing starts.","triggerScenarios":"Calling ProcStatUtil.parse/parseWithBufferForPath for a pid whose /proc/<pid>/stat cannot be opened: the process exited between listing and reading, the path does not exist, or the kernel/security module denies open.","commonSituations":"Short-lived child processes dying before the battery canary polls them; restricted SELinux policies on some Android vendors; reading stats of other users' processes on non-rooted devices.","solutions":["Catch ParseException around parse calls and skip/ignore that pid (transient process-exit is expected).","Verify the target pid is still alive (e.g. check /proc/<pid> exists or Process.isThreadRunning) before parsing.","Retry on the next sampling tick; if it fails persistently for the app's own pid, log the device/SELinux context.","Ensure the reader path points to the app's own process stats when lacking permission to read others."],"exampleFix":"// before\nStatModel stat = ProcStatUtil.instance.parse(pid);\n// after\ntry {\n    StatModel stat = ProcStatUtil.instance.parse(pid);\n} catch (ProcStatUtil.ParseException e) {\n    // process died or file unreadable; skip this tick\n    return;\n}","handlingStrategy":"try-catch","validationCode":"java.io.File f = new File(\"/proc/\" + pid + \"/stat\");\nif (!f.exists() || !f.canRead()) { /* skip pid */ }","typeGuard":null,"tryCatchPattern":"try { StatModel s = ProcStatUtil.instance.parse(pid); } catch (ProcStatUtil.ParseException e) { Log.w(TAG, \"stat open failed: \" + e.getMessage()); }","preventionTips":["Check pid liveness before each sample","Only read the app's own /proc stats unless root privileges are available","Treat each parse as best-effort; never let one pid failure break the sampling loop","Log device/SELinux context for persistent failures"],"tags":["android","proc-stat","io","process-monitoring"],"backgroundTag":"file-open-failed","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"}