{"record":{"id":"638e4b86449c335c","repo":"Tencent/matrix","slug":"fialed-to-create-new-hprof-file-since-path-absol","errorCode":null,"errorMessage":"fialed to create new hprof file since path: $absolutePath is not writable","messagePattern":"fialed to create new hprof file since path: \\$absolutePath is not writable","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-android/src/main/java/com/tencent/matrix/resource/dumper/HprofFileManager.kt","lineNumber":66,"sourceCode":"    fun prepareHprofFile(prefix: String = \"\", deleteSoon: Boolean = false): File {\n        hprofStorageDir.prepare(deleteSoon)\n        return File(hprofStorageDir, getHprofFileName(prefix))\n    }\n\n    fun clearAll() {\n        hprofStorageDir.deleteRecursively()\n    }\n\n    private fun File.prepare(deleteSoon: Boolean) {\n        reserve()\n        makeSureEnoughSpace(deleteSoon)\n    }\n\n    private fun File.reserve() {\n        if (!exists() && (!mkdirs() || !canWrite())) {\n            \"fialed to create new hprof file since path: $absolutePath is not writable\".let {\n                MatrixLog.e(TAG, it)\n                throw FileNotFoundException(it)\n            }\n        }\n    }\n\n    private fun File.makeSureEnoughSpace(deleteSoon: Boolean) {\n        if (!isDirectory) {\n            return\n        }\n        lru()\n        if (freeSpace < CLEAN_THRESHOLD) {\n            listFiles()?.forEach { it.delete() }\n        }\n        if (freeSpace < if (deleteSoon) MIN_FREE_SPACE else CLEAN_THRESHOLD) {\n            throw FileNotFoundException(\"free space($freeSpace) less than $CLEAN_THRESHOLD, skip dump hprof\")\n        }\n    }\n\n    private fun File.lru() {","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-android/src/main/java/com/tencent/matrix/resource/dumper/HprofFileManager.kt#L48-L84","documentation":"HprofFileManager's File.reserve() throws FileNotFoundException when the hprof output directory neither exists nor can be created/made writable (mkdirs() fails or canWrite() is false). It logs the message and throws so callers fail fast instead of writing hprof dumps to an unusable location.","triggerScenarios":"Preparing the hprof directory (via prepare -> reserve) at a path where mkdirs() fails (read-only filesystem, missing parent permissions, storage unmounted) or where the created directory is not writable.","commonSituations":"App targeting scoped storage paths it cannot write; external storage unmounted/full; configured hprof dir under a path not created due to SELinux/permission restrictions on certain OEM ROMs.","solutions":["Use an app-private directory like context.cacheDir or context.filesDir for hprof output.","Check available storage and mount state (Environment.getExternalStorageState) before dumping.","Request/verify write permissions (legacy WRITE_EXTERNAL_STORAGE if using shared storage).","Catch FileNotFoundException from the dumper and fall back to an alternate directory."],"exampleFix":"// before\nval hprofDir = File(Environment.getExternalStorageDirectory(), \"hprof\") // may be unwritable\n// after\nval hprofDir = File(context.cacheDir, \"hprof\").apply { mkdirs() }\nHprofFileManager(context, hprofDir, maxSpace)","handlingStrategy":"fallback","validationCode":"fun usableHprofDir(context: Context, preferred: File): File {\n  return if (preferred.exists() || preferred.mkdirs()) {\n    if (preferred.canWrite()) preferred else File(context.cacheDir, \"hprof\").apply { mkdirs() }\n  } else File(context.cacheDir, \"hprof\").apply { mkdirs() }\n}","typeGuard":"fun File.isWritableDir(): Boolean = isDirectory && canWrite()","tryCatchPattern":"try {\n  hprofFileManager.prepare()\n} catch (e: FileNotFoundException) {\n  MatrixLog.e(TAG, \"hprof dir unusable, falling back to cacheDir\")\n  hprofFileManager = HprofFileManager(context, File(context.cacheDir, \"hprof\"), maxSpace)\n  hprofFileManager.prepare()\n}","preventionTips":["Always configure hprof output under context.cacheDir or filesDir.","Check storage state and free space before triggering hprof dumps.","Handle FileNotFoundException from the dumper with a fallback directory rather than crashing leak reporting."],"tags":["android","filesystem","hprof","file-write-permission-denied"],"backgroundTag":"file-write-permission-denied","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"}