Tencent/tinker · error · TinkerRuntimeException

checkResInstall failed

Error message

checkResInstall failed

What it means

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.

Solutions

  1. Ensure the resource patch actually changes at least the resource Tinker uses for verification and is built with matching plugin/SDK versions.
  2. Rebuild and republish the patch; if the failure is device-specific, exclude resource patches on that model via server-side patch targeting.
  3. Update Tinker — newer versions handle N+ ResourcesImpl and notification/RemoteViews edge cases better.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before publishing: ensure patch changes a resource and rebuilds cleanly
// Locally verify patched apk contains expected resources:
// aapt dump resources patched/resources.apk | grep <marker>

Try / catch

try {
    TinkerResourcePatcher.monkeyPatchExistingResources(context, externalResourceFile);
} catch (TinkerRuntimeException e) { /* CHECK_RES_INSTALL_FAIL */
    // resource swap not visible: kill current process to retry clean on next start
    ShareTinkerInternals.killAllOtherProcess(context);
    System.exit(0);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerResourcePatcher.java:332

            }
        }

        // Handle issues caused by WebView on Android N.
        // Issue: On Android N, if an activity contains a webview, when screen rotates
        // our resource patch may lost effects.
        // for 5.x/6.x, we found Couldn't expand RemoteView for StatusBarNotification Exception
        if (Build.VERSION.SDK_INT >= 24) {
            try {
                if (publicSourceDirField != null) {
                    publicSourceDirField.set(context.getApplicationInfo(), externalResourceFile);
                }
            } catch (Throwable thr) {
                ShareTinkerLog.printErrStackTrace(TAG, thr, "fail to process publicSourceDirField field hack.");
            }
        }

        if (!checkResUpdate(context)) {
            throw new TinkerRuntimeException(ShareConstants.CHECK_RES_INSTALL_FAIL);
        }

        installResourceInsuranceHacks(context, externalResourceFile);
    }

    private static void installResourceInsuranceHacks(Context context, String patchedResApkPath) {
        try {
            final Object activityThread = ShareReflectUtil.getActivityThread(context, null);
            final Field mHField = ShareReflectUtil.findField(activityThread, "mH");
            final Handler mH = (Handler) mHField.get(activityThread);
            final Field mCallbackField = ShareReflectUtil.findField(Handler.class, "mCallback");
            final Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);
            if (!(originCallback instanceof ResourceInsuranceHandlerCallback)) {
                final ResourceInsuranceHandlerCallback hackCallback = new ResourceInsuranceHandlerCallback(
                        context, patchedResApkPath, originCallback, mH.getClass());
                mCallbackField.set(mH, hackCallback);
            } else {
                ShareTinkerLog.w(TAG, "installResourceInsuranceHacks: already installed, skip rest logic.");

View on GitHub (pinned to 1b7ea02c23)