Tencent/tinker · error · TinkerRuntimeException

context is null

Error message

context is null

What it means

Thrown by ShareTinkerInternals.cleanPatch(Context) when it is invoked with a null Context. cleanPatch removes the Tinker patch directory (tinker/), the patch info file and lock file, so it needs a real Context to locate app storage. A null Context means the caller (often Tinker.cleanPatch or a service with a destroyed reference) passed an invalid argument.

Source

Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareTinkerInternals.java:740

        int i = 0;
        for (; i < chr.length; i++) {
            if (chr[i] > 127) {
                chr[i] = 0;
                cutFlg = true;
                break;
            }
        }

        if (cutFlg) {
            return new String(chr, 0, i);
        } else {
            return src;
        }
    }

    public static void cleanPatch(Context context) {
        if (context == null) {
            throw new TinkerRuntimeException("context is null");
        }
        final File tinkerDir = SharePatchFileUtil.getPatchDirectory(context);
        if (!tinkerDir.exists()) {
            ShareTinkerLog.printErrStackTrace(TAG, new Throwable(),"try to clean patch while there're not any applied patches.");
            return;
        }
        final File patchInfoFile = SharePatchFileUtil.getPatchInfoFile(tinkerDir.getAbsolutePath());
        if (!patchInfoFile.exists()) {
            ShareTinkerLog.printErrStackTrace(TAG, new Throwable(), "try to clean patch while patch info file does not exist.");
            return;
        }
        final File patchInfoLockFile = SharePatchFileUtil.getPatchInfoLockFile(tinkerDir.getAbsolutePath());
        final SharePatchInfo patchInfo = SharePatchInfo.readAndCheckPropertyWithLock(patchInfoFile, patchInfoLockFile);
        if (patchInfo != null) {
            patchInfo.newVersion = "";
            patchInfo.versionToRemove = "";
            SharePatchInfo.rewritePatchInfoFileWithLock(patchInfoFile, patchInfo, patchInfoLockFile);
        } else {

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Pass the application Context (getApplicationContext()) instead of a possibly-null field or parameter
  2. Null-check the Context before invoking cleanPatch in your cleanup/crash-handler code
  3. If calling Tinker APIs, prefer Tinker.with(appContext).cleanPatch() which manages Context internally

Example fix

// before
ShareTinkerInternals.cleanPatch(maybeNullContext);

// after
Context ctx = maybeNullContext != null ? maybeNullContext : applicationContext;
if (ctx != null) {
    ShareTinkerInternals.cleanPatch(ctx);
}
Defensive patterns

Strategy: validation

Validate before calling

if (context == null) {
    Log.w(TAG, "skip cleanPatch: no context");
} else {
    ShareTinkerInternals.cleanPatch(context);
}

Prevention

When it happens

Trigger: Calling TinkerInternals.cleanPatch(null) directly, or calling Tinker.cleanPatch / Tinker.cleanPatchWithContext after the retained Context was cleared (e.g., a Service/BroadcastReceiver whose Context member is null, or custom entry code that captures a nullable Context).

Common situations: Wiring 'clean patch on crash' or 'rollback' logic in Application subclass or a crash handler where the Context variable is null; calling cleanup from a background process path that has no valid Context; unit tests that pass null.

Related errors


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