Tencent/tinker · error · TinkerRuntimeException

intentResult must not be null.

Error message

intentResult must not be null.

What it means

Tinker.install(Intent, Class, AbstractPatch) is the low-level install used after the patch-loading phase: the Intent carries the load result produced by the loader in TinkerApplication. A null intentResult means the load outcome is unknown/absent, and tinker refuses to finish installation rather than fabricate a load result.

Source

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

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

        ShareTinkerLog.i(TAG, "try to install tinker, isEnable: %b, version: %s", isTinkerEnabled(), ShareConstants.TINKER_VERSION);

        if (!isTinkerEnabled()) {
            ShareTinkerLog.e(TAG, "tinker is disabled");
            return;
        }
        if (intentResult == null) {
            throw new TinkerRuntimeException("intentResult must not be null.");
        }
        tinkerLoadResult = new TinkerLoadResult();
        tinkerLoadResult.parseTinkerResult(getContext(), intentResult);
        //after load code set
        loadReporter.onLoadResult(patchDirectory, tinkerLoadResult.loadCode, tinkerLoadResult.costTime);

        if (!loaded) {
            ShareTinkerLog.w(TAG, "tinker load fail!");
        }
    }

    /**
     * set tinkerPatchServiceNotificationId
     *
     * @param id
     */
    public void setPatchServiceNotificationId(int id) {
        TinkerPatchService.setTinkerNotificationId(id);

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Prefer the no-arg tinker.install() overload after the loader has run, letting tinker read the persisted load result.
  2. If using the Intent overload, pass the exact intent delivered by the loading phase (TinkerApplicationInternals), never null.
  3. Ensure your Application delegates to the tinker loader (via TinkerApplication or generated stub) before install.
  4. Gate on intentResult != null or TinkerLoadResult presence before calling the Intent overload.

Example fix

// before
tinker.install(null, ResultService.class, new UpgradePatch());

// after
tinker.install(); // reads the load result recorded by the loader
Defensive patterns

Strategy: validation

Validate before calling

// Prefer the no-arg overload after the loader ran:
if (tinkerLoadResultAlreadyAvailable()) {
    tinker.install();
} else if (loadResultIntent != null) {
    tinker.install(loadResultIntent, ResultService.class, new UpgradePatch());
} else {
    throw new IllegalStateException("tinker load result unavailable");
}

Prevention

When it happens

Trigger: Invoking tinker.install(intentResult, serviceClass, upgradePatch) with a null Intent — typically when custom code calls install manually instead of letting TinkerApplication/TinkerApplicationInternals deliver the load-result intent, or when using the generated application incorrectly.

Common situations: Migrating from the annotation-based TinkerApplication to manual initialization and passing null; calling install in a process where the patch loader never ran; refactors that drop the load-result intent plumbing.

Related errors


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