Tencent/tinker · error · TinkerRuntimeException

Context must not be null.

Error message

Context must not be null.

What it means

Tinker.Builder's constructor immediately rejects a null Context. The builder needs a Context to derive process identity (main vs :patch), the patch directory, and info files, so a null context makes the whole configuration meaningless and fails fast.

Source

Thrown at tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java:350

        private final boolean mainProcess;
        private final boolean patchProcess;

        private int status = -1;
        private LoadReporter  loadReporter;
        private PatchReporter patchReporter;
        private PatchListener listener;
        private AbstractFilePatch patcher;
        private File          patchDirectory;
        private File          patchInfoFile;
        private File          patchInfoLockFile;
        private Boolean       tinkerLoadVerifyFlag;

        /**
         * Start building a new {@link Tinker} instance.
         */
        public Builder(Context context) {
            if (context == null) {
                throw new TinkerRuntimeException("Context must not be null.");
            }
            this.context = context;
            this.mainProcess = TinkerServiceInternals.isInMainProcess(context);
            this.patchProcess = TinkerServiceInternals.isInTinkerPatchServiceProcess(context);
            this.patchDirectory = SharePatchFileUtil.getPatchDirectory(context);
            if (this.patchDirectory == null) {
                ShareTinkerLog.e(TAG, "patchDirectory is null!");
                return;
            }
            this.patchInfoFile = SharePatchFileUtil.getPatchInfoFile(patchDirectory.getAbsolutePath());
            this.patchInfoLockFile = SharePatchFileUtil.getPatchInfoLockFile(patchDirectory.getAbsolutePath());
            ShareTinkerLog.w(TAG, "tinker patch directory: %s", patchDirectory);
        }

        public Builder tinkerFlags(int tinkerFlags) {
            if (this.status != -1) {
                throw new TinkerRuntimeException("tinkerFlag is already set.");
            }

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Pass applicationContext, and construct the Builder only after the context is attached.
  2. In ApplicationLike, create the builder in onCreate (not earlier lifecycle hooks) when in doubt.
  3. Add a null assertion upstream so the failure points at the real missing dependency.

Example fix

// before
public MyAppLike(Application app) {
    this.builder = new Tinker.Builder(this.context); // context not yet set -> null
}

// after
@Override public void onCreate() {
    this.builder = new Tinker.Builder(getApplication().getApplicationContext());
}
Defensive patterns

Strategy: validation

Validate before calling

if (context == null) throw new IllegalArgumentException("context required before tinker init");
Tinker.Builder builder = new Tinker.Builder(context.getApplicationContext());

Type guard

public static boolean isValidContext(Context c) {
    return c != null && c.getApplicationContext() != null;
}

Prevention

When it happens

Trigger: Constructing new Tinker.Builder(null) — usually because a Context field was not yet assigned (constructor ordering), a DI-provided context was null, or a test passed null.

Common situations: Custom ApplicationLike subclasses that build a Tinker in onBaseContextAttached before attachBaseContext finishes; unit tests without Robolectric; refactor moving builder creation before context initialization.

Related errors


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