{"record":{"id":"6316af1132988d71","repo":"Tencent/tinker","slug":"checkresinstall-failed","errorCode":null,"errorMessage":"checkResInstall failed","messagePattern":"checkResInstall failed","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerResourcePatcher.java","lineNumber":332,"sourceCode":"            }\n        }\n\n        // Handle issues caused by WebView on Android N.\n        // Issue: On Android N, if an activity contains a webview, when screen rotates\n        // our resource patch may lost effects.\n        // for 5.x/6.x, we found Couldn't expand RemoteView for StatusBarNotification Exception\n        if (Build.VERSION.SDK_INT >= 24) {\n            try {\n                if (publicSourceDirField != null) {\n                    publicSourceDirField.set(context.getApplicationInfo(), externalResourceFile);\n                }\n            } catch (Throwable thr) {\n                ShareTinkerLog.printErrStackTrace(TAG, thr, \"fail to process publicSourceDirField field hack.\");\n            }\n        }\n\n        if (!checkResUpdate(context)) {\n            throw new TinkerRuntimeException(ShareConstants.CHECK_RES_INSTALL_FAIL);\n        }\n\n        installResourceInsuranceHacks(context, externalResourceFile);\n    }\n\n    private static void installResourceInsuranceHacks(Context context, String patchedResApkPath) {\n        try {\n            final Object activityThread = ShareReflectUtil.getActivityThread(context, null);\n            final Field mHField = ShareReflectUtil.findField(activityThread, \"mH\");\n            final Handler mH = (Handler) mHField.get(activityThread);\n            final Field mCallbackField = ShareReflectUtil.findField(Handler.class, \"mCallback\");\n            final Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);\n            if (!(originCallback instanceof ResourceInsuranceHandlerCallback)) {\n                final ResourceInsuranceHandlerCallback hackCallback = new ResourceInsuranceHandlerCallback(\n                        context, patchedResApkPath, originCallback, mH.getClass());\n                mCallbackField.set(mH, hackCallback);\n            } else {\n                ShareTinkerLog.w(TAG, \"installResourceInsuranceHacks: already installed, skip rest logic.\");","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerResourcePatcher.java#L314-L350","documentation":"After swapping AssetManagers into every Resources instance, Tinker calls checkResUpdate to confirm a resource queried through the current context actually resolves to a patched value (e.g. a new entry). CHECK_RES_INSTALL_FAIL means the swap did not take effect from the caller's perspective — patched resources are not visible even though the injection code ran.","triggerScenarios":"Some Resources/Theme instances still referencing the old AssetManager (webview-held Resources, another Resources created after enumeration), a resources patch whose checked marker resource is unchanged/absent, or an OEM resource caching layer ignoring the swap.","commonSituations":"Resource patches on N+ where WebView or LayoutInflater caches typed values; patches that modify no recognizable resource so the check cannot find an expected difference; partial injection because the app had created Resources before attachBaseContext completed.","solutions":["Ensure the resource patch actually changes at least the resource Tinker uses for verification and is built with matching plugin/SDK versions.","Rebuild and republish the patch; if the failure is device-specific, exclude resource patches on that model via server-side patch targeting.","Update Tinker — newer versions handle N+ ResourcesImpl and notification/RemoteViews edge cases better."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before publishing: ensure patch changes a resource and rebuilds cleanly\n// Locally verify patched apk contains expected resources:\n// aapt dump resources patched/resources.apk | grep <marker>","typeGuard":null,"tryCatchPattern":"try {\n    TinkerResourcePatcher.monkeyPatchExistingResources(context, externalResourceFile);\n} catch (TinkerRuntimeException e) { /* CHECK_RES_INSTALL_FAIL */\n    // resource swap not visible: kill current process to retry clean on next start\n    ShareTinkerInternals.killAllOtherProcess(context);\n    System.exit(0);\n}","preventionTips":["Always include at least one changed resource in resource patches.","Match gradle plugin and SDK versions when building resource patches.","After failed resource patch load, prefer process restart over continuing with mixed resources."],"tags":["android","resources","patch-verification","tinker"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}