Tencent/tinker · error · IOException
Tinker Exception:FileLockHelper lock file failed: {}
Error message
Tinker Exception:FileLockHelper lock file failed: {} What it means
ShareFileLockHelper acquires an exclusive java.nio FileLock on a lock file, retrying with sleeps; if localFileLock is still null after all attempts it throws IOException("Tinker Exception:FileLockHelper lock file failed: <path>") with the last saveException as cause. FileLock.tryLock can fail on filesystems that do not support POSIX locks or when another process/thread holds the lock.
Source
Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareFileLockHelper.java:66
if (isGetLockSuccess) {
break;
}
} catch (Exception e) {
saveException = e;
ShareTinkerLog.e(TAG, "getInfoLock Thread failed time:" + LOCK_WAIT_EACH_TIME);
}
//it can just sleep 0, afraid of cpu scheduling
try {
Thread.sleep(LOCK_WAIT_EACH_TIME);
} catch (Exception ignore) {
ShareTinkerLog.e(TAG, "getInfoLock Thread sleep exception", ignore);
}
}
if (localFileLock == null) {
throw new IOException("Tinker Exception:FileLockHelper lock file failed: " + lockFile.getAbsolutePath(), saveException);
}
fileLock = localFileLock;
}
public static ShareFileLockHelper getFileLock(File lockFile) throws IOException {
return new ShareFileLockHelper(lockFile);
}
@Override
public void close() throws IOException {
try {
if (fileLock != null) {
fileLock.release();
}
} finally {
if (outputStream != null) {
outputStream.close();
}View on GitHub (pinned to 1b7ea02c23)
Solutions
- Ensure only one process performs patch operations (guard with a process-level lock or route patching to the main process).
- Make sure the lock file's parent directory exists and is writable before acquiring.
- If a stale lock persists after a crash, reboot or clear the app's tinker directory so the lock file is recreated.
- Catch IOException around getFileLock callers (readAndCheckPropertyWithLock / rewritePatchInfoFileWithLock) and surface a retryable patch failure instead of crashing.
- Upgrade Tinker — newer versions tune lock wait/retry behavior.
Example fix
// before
fileLock = ShareFileLockHelper.getFileLock(lockFile);
// after
try {
fileLock = ShareFileLockHelper.getFileLock(lockFile);
} catch (IOException e) {
ShareTinkerLog.w(TAG, "lock busy, retry patch later", e);
return false;
} Defensive patterns
Strategy: retry
Validate before calling
File lockParent = lockFile.getParentFile();
if (lockParent == null || (!lockParent.exists() && !lockParent.mkdirs())) {
// cannot lock: fix directory before calling getFileLock
}
if (!lockParent.canWrite()) {
// read-only storage: patch ops will fail
} Try / catch
try {
ShareFileLockHelper lock = ShareFileLockHelper.getFileLock(lockFile);
try { /* critical section */ } finally { lock.close(); }
} catch (IOException e) {
// lock acquisition failed after retries: back off and retry the whole op later
} Prevention
- Restrict patch loading/apply to a single process.
- Always close ShareFileLockHelper in a finally block.
- On persistent lock failure, clean the tinker lock files and retry once after process restart.
When it happens
Trigger: ShareFileLockHelper.getFileLock(lockFile) when tryLock() repeatedly throws IOException (e.g. lock held elsewhere, or the FS does not support locking) until the retry budget is exhausted.
Common situations: Patch info read/rewrite while a previous Tinker operation crashed holding the lock on some devices; multi-process apps where two processes patch simultaneously; certain OEM filesystems/emulated storage where FileLock is unsupported; lock file on a read-only or corrupted directory.
Related errors
- Tinker Exception:FileLockHelper lock file failed: {}
- readAndCheckPropertyWithLock fail
- rewritePatchInfoFileWithLock fail
- patch ${type} extract failed (${message}).
- patch %s extract failed (%s).
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/a232d9f41080b2d7.
Report an issue: GitHub.