Tencent/tinker · error · TinkerRuntimeException

you must install tinker before get tinker sInstance

Error message

you must install tinker before get tinker sInstance

What it means

Tinker.with(Context) is the accessor for the Tinker singleton, but it refuses to run before TinkerInstaller.install(...) (which sets sInstalled = true), throwing TinkerRuntimeException("you must install tinker before get tinker sInstance"). This enforces the library's initialization contract: install defines the reporters, listener and flags before anything can obtain the instance. In the no-op artifact the same guard exists so misordered code fails identically in no-op builds.

Source

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

        this.tinkerFlags = tinkerFlags;
        this.patchDirectory = patchDirectory;
        this.patchInfoFile = patchInfoFile;
        this.patchInfoLockFile = patchInfoLockFile;
        this.isMainProcess = isInMainProc;
        this.tinkerLoadVerifyFlag = tinkerLoadVerifyFlag;
        this.isPatchProcess = isPatchProcess;
    }

    /**
     * init with default config tinker
     * for safer, you must use @{link TinkerInstaller.install} first!
     *
     * @param context we will use the application context
     * @return the Tinker object
     */
    public static Tinker with(Context context) {
        if (!sInstalled) {
            throw new TinkerRuntimeException("you must install tinker before get tinker sInstance");
        }
        synchronized (Tinker.class) {
            if (sInstance == null) {
                sInstance = new Builder(context).build();
            }
        }
        return sInstance;
    }

    /**
     * create custom tinker by {@link Tinker.Builder}
     * please do it when very first your app start.
     *
     * @param tinker
     */
    public static void create(Tinker tinker) {
        if (sInstance != null) {
            throw new TinkerRuntimeException("Tinker instance is already set.");

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Call TinkerInstaller.install(defaultApplicationLike, ...) at the very start of Application.onCreate (or attachBaseContext) before any Tinker.with() consumer runs.
  2. Guard every accessor with Tinker.isTinkerInstalled() (the API exists on this class) and degrade gracefully when not installed.
  3. Verify install runs in ALL processes that touch Tinker — check your process-splitting logic in Application.

Example fix

// before
public void onCreate() {
    super.onCreate();
    Tinker.with(this).getTinkerLoadResultIfWithPatch(); // throws
    TinkerInstaller.install(appLike, ...);
}

// after
public void onCreate() {
    super.onCreate();
    TinkerInstaller.install(appLike, loadReport, patchReport, patchListener, ...);
    if (Tinker.isTinkerInstalled()) {
        Tinker.with(this).getTinkerLoadResultIfWithPatch();
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if (Tinker.isTinkerInstalled()) {
    Tinker tinker = Tinker.with(context);
    // use tinker...
} else {
    Log.w(TAG, "Tinker not installed; skipping Tinker.with()");
}

Try / catch

try {
    Tinker tinker = Tinker.with(context);
} catch (TinkerRuntimeException e) {
    // install was never called in this process
    Log.w(TAG, "Tinker.with before install", e);
}

Prevention

When it happens

Trigger: Calling Tinker.with(context) (directly or via helpers like TinkerLoadLibrary/upgrade processors that internally fetch the instance) before TinkerInstaller.install(context, ...) has run in this process.

Common situations: App code that queries Tinker.with() in Application.attachBaseContext while install happens later in onCreate; a secondary process (patch service, push process) whose Application path skips the install call; unit tests or no-op build variants where install was omitted but downstream calls remain.

Related errors


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