{"record":{"id":"34fc579d4fab5eb7","repo":"Tencent/tinker","slug":"patch-dex-file-directory-not-found-warning-why-th-34fc57","errorCode":null,"errorMessage":"patch dex file directory not found, warning why the path is null!!!!","messagePattern":"patch dex file directory not found, warning why the path is null!!!!","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/TinkerLoadResult.java","lineNumber":201,"sourceCode":"                    ShareConstants.TYPE_PATCH_FILE, false);\n                break;\n            case ShareConstants.ERROR_LOAD_PATCH_PACKAGE_CHECK_FAIL:\n                ShareTinkerLog.i(TAG, \"patch package check fail\");\n                if (patchVersionFile == null) {\n                    throw new TinkerRuntimeException(\"error patch package check fail , but file is null\");\n                }\n                int errorCode = intentResult.getIntExtra(ShareIntentUtil.INTENT_PATCH_PACKAGE_PATCH_CHECK, ShareConstants.ERROR_LOAD_GET_INTENT_FAIL);\n                tinker.getLoadReporter().onLoadPackageCheckFail(patchVersionFile, errorCode);\n                break;\n            case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_DIRECTORY_NOT_EXIST:\n                if (dexDirectory != null) {\n                    ShareTinkerLog.e(TAG, \"patch dex file directory not found:%s\", dexDirectory.getAbsolutePath());\n                    tinker.getLoadReporter().onLoadFileNotFound(dexDirectory,\n                        ShareConstants.TYPE_DEX, true);\n                } else {\n                    //should be not here\n                    ShareTinkerLog.e(TAG, \"patch dex file directory not found, warning why the path is null!!!!\");\n                    throw new TinkerRuntimeException(\"patch dex file directory not found, warning why the path is null!!!!\");\n                }\n                break;\n            case ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_FILE_NOT_EXIST:\n                String dexPath = ShareIntentUtil.getStringExtra(intentResult,\n                    ShareIntentUtil.INTENT_PATCH_MISSING_DEX_PATH);\n                if (dexPath != null) {\n                    //we only pass one missing file\n                    ShareTinkerLog.e(TAG, \"patch dex file not found:%s\", dexPath);\n                    tinker.getLoadReporter().onLoadFileNotFound(new File(dexPath),\n                        ShareConstants.TYPE_DEX, false);\n\n                } else {\n                    ShareTinkerLog.e(TAG, \"patch dex file not found, but path is null!!!!\");\n                    throw new TinkerRuntimeException(\"patch dex file not found, but path is null!!!!\");\n                    // tinker.getLoadReporter().onLoadFileNotFound(null,\n                    //     ShareConstants.TYPE_DEX, false);\n                }\n                break;","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/TinkerLoadResult.java#L183-L219","documentation":"Thrown from TinkerLoadResult while handling ERROR_LOAD_PATCH_VERSION_DEX_DIRECTORY_NOT_EXIST: the loader reported that the patch's dex directory is missing, but the computed dexDirectory File is null. The comment in source ('should be not here') marks it as a should-never-happen defensive branch; hitting it means the load result intent and the locally reconstructed patch paths disagree — an internal state inconsistency rather than a user-input error.","triggerScenarios":"The loader returns ERROR_LOAD_PATCH_VERSION_DEX_DIRECTORY_NOT_EXIST while dexDirectory (built from the patch version directory) is null — i.e. patch info/JSON metadata exists enough to attempt a load but the version directory path could not be derived. Happens when the patch metadata is corrupted or the tinker directory layout was altered externally.","commonSituations":"Corrupted patch info file (partially written JSON); tinker directory structure tampered with by device cleaners, Xposed-style tools, or ADB; running a patch built by a mismatched tinker gradle plugin version that writes a different layout.","solutions":["Call Tinker.with(context).cleanPatch() to remove the inconsistent patch state, then re-apply the patch.","Reproduce and inspect /data/data/<pkg>/tinker/: check that patch.info and the version directory match; if not, wipe via cleanPatch.","Make sure only official Tinker APIs (TinkerInstaller) manage the tinker directory; never delete or move files inside it manually.","Align the tinker Android library and gradle plugin versions in your build."],"exampleFix":"// after catching this in a global handler\ncatch (TinkerRuntimeException e) {\n    if (e.getMessage().contains(\"dex file directory not found\")) {\n        Tinker.with(appContext).cleanPatch();\n    }\n}","handlingStrategy":"try-catch","validationCode":"Tinker tinker = Tinker.with(context);\nif (tinker.isTinkerLoaded()) {\n    File dexDir = new File(tinker.getTinkerLoadResultIfPresent().patchVersionDirectory, \"dex\");\n    if (!dexDir.isDirectory()) tinker.cleanPatch();\n}","typeGuard":null,"tryCatchPattern":"catch (TinkerRuntimeException e) {\n    if (e.getMessage().contains(\"dex file directory not found\")) {\n        Tinker.with(app).cleanPatch();\n    } else throw e;\n}","preventionTips":["Let only Tinker APIs manage /tinker directories","Re-apply patches after cleanPatch instead of retrying loads on broken state"],"tags":["tinker","hotpatch","android","corrupted-state","dex"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}