Tencent/tinker · error · TinkerRuntimeException

Context must not be null.

Error message

Context must not be null.

What it means

Tinker.Builder's constructor throws TinkerRuntimeException("Context must not be null.") when passed a null Context. The builder immediately uses the context to detect the current process and compute the patch directory, so a null context cannot be deferred; the guard fails fast at construction rather than later during build().

Source

Thrown at tinker-android/tinker-android-lib-no-op/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java:299

        private final Context context;
        private final boolean mainProcess;
        private final boolean patchProcess;

        private int status = -1;
        private LoadReporter  loadReporter;
        private PatchReporter patchReporter;
        private PatchListener listener;
        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 the application context obtained in attachBaseContext/onCreate (or ApplicationLike.getApplication()) — never an uninitialized field.
  2. Null-check the context at the call site with a clear error naming the caller when migrating old code.
  3. In unit tests, use RuntimeEnvironment.application (Robolectric) rather than null.

Example fix

// before
public class MyApp extends Application {
    private final Tinker.Builder b = new Tinker.Builder(context); // field init: context null

// after
public class MyApp extends Application {
    private Tinker.Builder b;
    @Override public void onCreate() {
        super.onCreate();
        b = new Tinker.Builder(getApplicationContext());
    }
}
Defensive patterns

Strategy: validation

Validate before calling

Context ctx = (application != null) ? application.getApplicationContext() : null;
if (ctx == null) throw new IllegalStateException("no context for Tinker init");
Tinker.Builder builder = new Tinker.Builder(ctx);

Prevention

When it happens

Trigger: new Tinker.Builder(null) — typically because the context field was not yet assigned (call from a constructor or static init before onCreate), or a helper received null and forwarded it.

Common situations: Custom Application subclasses calling the builder before super.onCreate()/attachBaseContext finished setting up fields; test harnesses passing a null or mocked-null context; refactor moving Tinker init into a class whose context argument became optional.

Related errors


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