Tencent/tinker · error · TinkerRuntimeException

Tinker instance is already set.

Error message

Tinker instance is already set.

What it means

Tinker.create(tinker) explicitly initializes the singleton with a custom-built instance and enforces single invocation: a second call while sInstance != null throws. This prevents two different configurations from silently replacing each other.

Source

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

            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.");
        }
        sInstance = tinker;
    }

    public static boolean isTinkerInstalled() {
        return sInstalled;
    }

    /**
     * you must install tinker first!!
     *
     * @param intentResult
     * @param serviceClass
     * @param upgradePatch
     */
    public void install(Intent intentResult, Class<? extends AbstractResultService> serviceClass,
                        AbstractPatch upgradePatch) {
        sInstalled = true;

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Initialize tinker exactly once per process, in ApplicationLike.onCreate.
  2. Guard with Tinker.isTinkerInstalled() / a static boolean before calling create.
  3. If multiple modules need tinker, centralize ownership of initialization in the app module.

Example fix

// before
Tinker.create(myTinker); // module A
Tinker.create(theirTinker); // module B -> throws

// after
if (!Tinker.isTinkerInstalled()) {
    Tinker.create(myTinker);
}
Defensive patterns

Strategy: validation

Validate before calling

synchronized (Tinker.class) {
    if (!Tinker.isTinkerInstalled()) {
        Tinker.create(customTinker);
    }
}

Type guard

public static boolean isTinkerSingletonPresent() {
    return Tinker.isTinkerInstalled(); // with()/create both land on installed state
}

Prevention

When it happens

Trigger: Calling Tinker.create(...) twice in one process, or mixing Tinker.create with the lazy path Tinker.with(...) — with() also populates sInstance, so calling create after any with() call throws.

Common situations: SDK modules or third-party wrappers that each try to initialize tinker; app calling create in onCreate while a library earlier obtained Tinker.with(context); process-wide init code that runs on configuration change or re-attach.

Related errors


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