Tencent/tinker · critical · TinkerRuntimeException

rewritePatchInfoFileWithLock fail

Error message

rewritePatchInfoFileWithLock fail

What it means

SharePatchInfo.rewritePatchInfoFileWithLock takes the lock file and rewrites the info file (rewritePatchInfoFile). Any exception during locking or the atomic rewrite is wrapped in TinkerRuntimeException('rewritePatchInfoFileWithLock fail'). Unlike the read path, this happens while persisting patch metadata — typically during patch apply/upgrade — so the patch state on disk may be out of sync.

Source

Thrown at tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/SharePatchInfo.java:106

        return patchInfo;
    }

    public static boolean rewritePatchInfoFileWithLock(File pathInfoFile, SharePatchInfo info, File lockFile) {
        if (pathInfoFile == null || info == null || lockFile == null) {
            return false;
        }
        File lockParentFile = lockFile.getParentFile();
        if (!lockParentFile.exists()) {
            lockParentFile.mkdirs();
        }
        boolean rewriteSuccess;
        ShareFileLockHelper fileLock = null;
        try {
            fileLock = ShareFileLockHelper.getFileLock(lockFile);
            rewriteSuccess = rewritePatchInfoFile(pathInfoFile, info);
        } catch (Exception e) {
            throw new TinkerRuntimeException("rewritePatchInfoFileWithLock fail", e);
        } finally {
            try {
                if (fileLock != null) {
                    fileLock.close();
                }
            } catch (IOException e) {
                ShareTinkerLog.i(TAG, "releaseInfoLock error", e);
            }

        }
        return rewriteSuccess;
    }

    private static SharePatchInfo readAndCheckProperty(File pathInfoFile) {
        boolean isReadPatchSuccessful = false;
        int numAttempts = 0;
        String oldVer = null;
        String newVer = null;

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Check and free device storage before applying patches; treat this failure as 'patch not applied' and retry the full apply flow.
  2. Ensure only the designated process applies patches and nothing else deletes the tinker directory concurrently.
  3. Call Tinker.cleanPatch() to return to a consistent base state, then re-download and re-apply.
  4. Inspect the exception cause (caused-by) — IOException points to storage, other causes to lock contention.

Example fix

// before
boolean ok = SharePatchInfo.rewritePatchInfoFileWithLock(infoFile, info, lockFile);

// after
boolean ok;
try {
    ok = SharePatchInfo.rewritePatchInfoFileWithLock(infoFile, info, lockFile);
} catch (TinkerRuntimeException e) {
    ShareTinkerLog.e(TAG, "rewrite info fail, patch state may be stale", e);
    ok = false;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (Environment.getExternalStorageState(...) is bad || dir.getFreeSpace() < MIN_BYTES) { /* defer patch apply */ }

Try / catch

catch TinkerRuntimeException 'rewritePatchInfoFileWithLock fail' -> mark patch apply as failed, cleanPatch(), retry on next launch

Prevention

When it happens

Trigger: Disk full or storage read-only when writing infoFile; lock file parent directory creation failing; serialization of the info throwing; the destination file being deleted concurrently by another process mid-write.

Common situations: Low-storage devices during patch apply; multiple processes (or a watchdog) cleaning the tinker directory while another applies a patch; file system errors after OTA.

Related errors


AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14). Data as JSON: /api/errors/d02035fc08020241. Report an issue: GitHub.