{"record":{"id":"4f0e72c47cfc0be1","repo":"Tencent/tinker","slug":"readandcheckpropertywithlock-fail-4f0e72","errorCode":null,"errorMessage":"readAndCheckPropertyWithLock fail","messagePattern":"readAndCheckPropertyWithLock fail","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/SharePatchInfo.java","lineNumber":92,"sourceCode":"        this.isRemoveInterpretOATDir = isRemoveInterpretOATDir;\n    }\n\n    public static SharePatchInfo readAndCheckPropertyWithLock(File pathInfoFile, File lockFile) {\n        if (pathInfoFile == null || lockFile == null) {\n            return null;\n        }\n        File lockParentFile = lockFile.getParentFile();\n        if (!lockParentFile.exists()) {\n            lockParentFile.mkdirs();\n        }\n\n        SharePatchInfo patchInfo;\n        ShareFileLockHelper fileLock = null;\n        try {\n            fileLock = ShareFileLockHelper.getFileLock(lockFile);\n            patchInfo = readAndCheckProperty(pathInfoFile);\n        } catch (Exception e) {\n            throw new TinkerRuntimeException(\"readAndCheckPropertyWithLock fail\", e);\n        } finally {\n            try {\n                if (fileLock != null) {\n                    fileLock.close();\n                }\n            } catch (IOException e) {\n                ShareTinkerLog.w(TAG, \"releaseInfoLock error\", e);\n            }\n        }\n\n        return patchInfo;\n    }\n\n    public static boolean rewritePatchInfoFileWithLock(File pathInfoFile, SharePatchInfo info, File lockFile) {\n        if (pathInfoFile == null || info == null || lockFile == null) {\n            return false;\n        }\n        File lockParentFile = lockFile.getParentFile();","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/SharePatchInfo.java#L74-L110","documentation":"SharePatchInfo.readAndCheckPropertyWithLock acquires a file lock and then reads/validates the patch info file (pathInfoFile). Any exception during lock acquisition, file read, or field checking is wrapped in TinkerRuntimeException(\"readAndCheckPropertyWithLock fail\", e). The cause identifies whether it was locking, IO, or content validation.","triggerScenarios":"Calling readAndCheckPropertyWithLock when the lock file cannot be locked (see FileLockHelper failure), the info file is missing/corrupted, or its fields (version strings, paths) fail validation.","commonSituations":"First patch load where /tinker/info is incomplete; concurrent access by two processes; corrupted info file after a crash mid-write; disk-full during read; stale lock from a previous run.","solutions":["Log the cause exception to distinguish lock failure vs corrupted info file.","Ensure the patch info directory is fully written (rewritePatchInfoFileWithLock) before reading, and that only one process loads patches.","If the info file is corrupted, clean the app's tinker directory (or reinstall) so patch state is rebuilt.","Free up storage and check file permissions on the info directory.","Catch TinkerRuntimeException around patch-load APIs and mark the patch as failed rather than crashing."],"exampleFix":"// before\npatchInfo = SharePatchInfo.readAndCheckPropertyWithLock(infoFile, lockFile);\n// after\ntry {\n    patchInfo = SharePatchInfo.readAndCheckPropertyWithLock(infoFile, lockFile);\n} catch (TinkerRuntimeException e) {\n    ShareTinkerLog.e(TAG, \"patch info unreadable, clean state\", e);\n    patchInfo = null;\n}","handlingStrategy":"try-catch","validationCode":"if (!infoFile.exists() || infoFile.length() == 0) {\n    // no patch info yet: nothing to read, skip the locked read\n}","typeGuard":null,"tryCatchPattern":"try {\n    patchInfo = SharePatchInfo.readAndCheckPropertyWithLock(infoFile, lockFile);\n} catch (TinkerRuntimeException e) {\n    Throwable cause = e.getCause(); // lock vs IO vs validation\n    patchInfo = null; // treat as 'no valid patch state'\n}","preventionTips":["Write patch info before reading it (correct apply ordering).","Single-process patch loading to avoid lock contention.","Free storage and ensure tinker directory writability before patch ops."],"tags":["android","tinker","patch-info","file-lock","io"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}