Tencent/tinker · critical · TinkerRuntimeException

ShareSecurityCheck init public key fail

Error message

ShareSecurityCheck init public key fail

What it means

ShareSecurityCheck.init catches every exception from PackageManager.getPackageInfo / signature access / md5 computation and rethrows TinkerRuntimeException("ShareSecurityCheck init public key fail", e). The original cause tells the story: NameNotFoundException, null signatures array, or digest failure. Without the app's public key md5, Tinker refuses to verify patches.

Source

Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareSecurityCheck.java:173

                }
            }
        }
        return false;
    }

    @SuppressLint("PackageManagerGetSignatures")
    private void init(Context context) {
        ByteArrayInputStream stream = null;
        try {
            PackageManager pm = context.getPackageManager();
            String packageName = context.getPackageName();
            PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            mPublicKeyMd5 = SharePatchFileUtil.getMD5(packageInfo.signatures[0].toByteArray());
            if (mPublicKeyMd5 == null) {
                throw new TinkerRuntimeException("get public key md5 is null");
            }
        } catch (Exception e) {
            throw new TinkerRuntimeException("ShareSecurityCheck init public key fail", e);
        } finally {
            SharePatchFileUtil.closeQuietly(stream);
        }
    }
}

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Inspect the cause: NameNotFoundException vs NullPointerException on signatures.
  2. Make sure the APK is release-signed and installed normally.
  3. Update Tinker to a version compatible with the target API level's signing APIs.
  4. Catch TinkerRuntimeException around TinkerInstaller.load / security check usage and report patch-load failure instead of crashing.
  5. Avoid triggering patch load from instrumented or mocked contexts.

Example fix

// before
TinkerInstaller.load(tinkerApplication);
// after
try {
    TinkerInstaller.load(tinkerApplication);
} catch (TinkerRuntimeException e) {
    ShareTinkerLog.e(TAG, "tinker init fail, disable patch", e);
    TinkerInternals.killTinkerApplicationProcess();
}
Defensive patterns

Strategy: try-catch

Validate before calling

try {
    PackageInfo pi = context.getPackageManager()
        .getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
    if (pi.signatures == null || pi.signatures.length == 0) {
        // signatures unavailable on this install: expect init to fail
    }
} catch (PackageManager.NameNotFoundException e) {
    // context/package mismatch: patching cannot be secured
}

Try / catch

try {
    TinkerInstaller.load(application);
} catch (TinkerRuntimeException e) {
    Throwable cause = e.getCause(); // PM failure, null signatures, digest error
    // disable tinker for this session, report to monitoring
}

Prevention

When it happens

Trigger: new ShareSecurityCheck(context) on devices/contexts where getPackageInfo with GET_SIGNATURES throws or packageInfo.signatures is null/empty — e.g. Android P+ deprecating GET_SIGNATURES without GET_SIGNING_CERTIFICATES handling, or unusual install contexts.

Common situations: Targeting newer Android versions where signature APIs changed; shared-user / system apps without standard signing metadata; test environments with unsigned builds; PM returning null signatures on some OEM ROMs.

Related errors


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