{"record":{"id":"92bd4ef972c24877","repo":"Tencent/tinker","slug":"checkdexinstall-failed","errorCode":null,"errorMessage":"checkDexInstall failed","messagePattern":"checkDexInstall failed","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"critical","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/SystemClassLoaderAdder.java","lineNumber":73,"sourceCode":"                                    boolean isProtectedApp, boolean useDLC) throws Throwable {\n        ShareTinkerLog.i(TAG, \"installDexes dexOptDir: \" + dexOptDir.getAbsolutePath() + \", dex size:\" + files.size());\n\n        if (!files.isEmpty()) {\n            files = createSortedAdditionalPathEntries(files);\n            ClassLoader classLoader = loader;\n            if (Build.VERSION.SDK_INT >= 24 && !isProtectedApp) {\n                classLoader = NewClassLoaderInjector.inject(application, loader, dexOptDir, useDLC, files);\n            } else {\n                injectDexesInternal(classLoader, files, dexOptDir);\n            }\n            //install done\n            sPatchDexCount = files.size();\n            ShareTinkerLog.i(TAG, \"after loaded classloader: \" + classLoader + \", dex size:\" + sPatchDexCount);\n\n            if (!checkDexInstall(classLoader)) {\n                //reset patch dex\n                SystemClassLoaderAdder.uninstallPatchDex(classLoader);\n                throw new TinkerRuntimeException(ShareConstants.CHECK_DEX_INSTALL_FAIL);\n            }\n        }\n    }\n\n    static void injectDexesInternal(ClassLoader cl, List<File> dexFiles, File optimizeDir) throws Throwable {\n        if (Build.VERSION.SDK_INT >= 23) {\n            V23.install(cl, dexFiles, optimizeDir);\n        } else if (Build.VERSION.SDK_INT >= 19) {\n            V19.install(cl, dexFiles, optimizeDir);\n        } else if (Build.VERSION.SDK_INT >= 14) {\n            V14.install(cl, dexFiles, optimizeDir);\n        } else {\n            V4.install(cl, dexFiles, optimizeDir);\n        }\n    }\n\n    public static void installApk(PathClassLoader loader, List<File> files) throws Throwable {\n        if (!files.isEmpty()) {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/SystemClassLoaderAdder.java#L55-L91","documentation":"SystemClassLoaderAdder.loadDexes injects the patch dex files into the app's ClassLoader (via NewClassLoaderInjector on SDK>=24 or injectDexesInternal), then runs checkDexInstall to verify the patch classes are actually loadable. If verification fails it uninstalls the patch dex and throws TinkerRuntimeException(CHECK_DEX_INSTALL_FAIL / 'checkDexInstall failed'). Injection succeeded but the loaded dex is unusable.","triggerScenarios":"checkDexInstall failing to load a known patch class: dex file corrupt, wrong-endian/ISA dex, odex mismatch with the running runtime, or classes failing verification on-device; also NewClassLoaderInjector-created loader not exposing the patch classes.","commonSituations":"Patch dex built with an incompatible build-tools/sdk version; 32/64-bit mismatch between patch odex and process; vendor ROMs blocking dex loading; proguard/manifest differences between base and patch causing the checked class to be absent.","solutions":["Verify the patch was built against the exact same base apk and tinker toolchain; rebuild and re-sign the patch.","Ensure the patch dex targets the same API/bytecode level and ABI as the running process (no 64-bit patch loaded into a 32-bit process).","Check checkDexInstall's logs for the underlying ClassNotFoundException/verify error to identify which class failed, then fix that class in the patch.","Upgrade tinker; loader fixes for specific Android versions (especially 8.x/9.xClassLoader injection) land regularly."],"exampleFix":"// before\nSystemClassLoaderAdder.loadDexes(loader, dexFiles, dexOptDir, false, false, isProtectedApp, false, ...);\n\n// after\ntry {\n    SystemClassLoaderAdder.loadDexes(loader, dexFiles, dexOptDir, false, false, isProtectedApp, false, ...);\n} catch (TinkerRuntimeException e) {\n    if (ShareConstants.CHECK_DEX_INSTALL_FAIL.equals(e.getMessage())) {\n        ShareTinkerLog.e(TAG, \"patch dex unusable, rolling back\", e);\n        Tinker.with(app).cleanPatch();\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch TinkerRuntimeException with message CHECK_DEX_INSTALL_FAIL -> the loader already uninstalled the patch dex; call cleanPatch() and report patch version as failed","preventionTips":["Always build patches against the exact base apk the device runs.","Match patch dex bytecode level and ABI with the running process.","Monitor which class fails checkDexInstall in logs to fix the patch content."],"tags":["dex-loading","classloader","patch-verify","android"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}