Tencent/tinker · critical · TinkerRuntimeException
upgradePatchProcessor is null.
Error message
upgradePatchProcessor is null.
What it means
Inside TinkerPatchService.doApplyPatch: the service is running, but the static upgradePatchProcessor was never set. That field is assigned by Tinker.install(...) -> TinkerPatchService.setPatchProcessor(...). So this throw means the :patch process is alive and handling an apply intent while Tinker was never installed in that process — an initialization-order/integration bug.
Source
Thrown at tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/service/TinkerPatchService.java:236
}
String path = getPatchPathExtra(intent);
if (path == null) {
ShareTinkerLog.e(TAG, "TinkerPatchService can't get the path extra, ignoring.");
return;
}
File patchFile = new File(path);
final boolean useEmergencyMode = getPatchUseEmergencyMode(intent);
long begin = SystemClock.elapsedRealtime();
boolean result;
long cost;
Throwable e = null;
PatchResult patchResult = new PatchResult();
try {
if (upgradePatchProcessor == null) {
throw new TinkerRuntimeException("upgradePatchProcessor is null.");
}
result = upgradePatchProcessor.tryPatch(context, path, useEmergencyMode, patchResult);
} catch (Throwable throwable) {
e = throwable;
result = false;
tinker.getPatchReporter().onPatchException(patchFile, e);
}
cost = SystemClock.elapsedRealtime() - begin;
tinker.getPatchReporter()
.onPatchResult(patchFile, result, cost);
patchResult.isSuccess = result;
patchResult.rawPatchFilePath = path;
patchResult.useEmergencyMode = useEmergencyMode;
patchResult.totalCostTime = cost;
patchResult.type = tinker.getCustomPatcher() == null ? PatchResult.PATCH_TYPE_BSDIFF : PatchResult.PATCH_TYPE_CUSTOM;
patchResult.e = e;View on GitHub (pinned to 1b7ea02c23)
Solutions
- Call TinkerInstaller.install unconditionally in your Application/DefaultApplicationLike.onCreate for every process, including the patch process.
- Do not gate install on runtime flags; install a no-op configuration instead of skipping install.
- If you catch exceptions around install, rethrow or disable the patch service so it never runs half-initialized.
- Ensure the tinker patch process is declared and named exactly as configured so the Application executes there too.
Example fix
// before
if (remoteConfig.tinkerEnabled) {
TinkerInstaller.install(appLike);
}
// after
TinkerInstaller.install(appLike); // always install; control enablement via tinkerFlags/isTinkerEnabled instead Defensive patterns
Strategy: validation
Validate before calling
if (!Tinker.isTinkerInstalled()) {
// cannot apply patches yet: defer instead of starting the service
deferPatchWorkUntilInstall();
return;
}
TinkerInstaller.onReceiveUpgradePatch(context, patchPath); Type guard
public static boolean canApplyPatches() {
return Tinker.isTinkerInstalled()
&& Tinker.isTinkerEnabled()
&& TinkerServiceInternals.isInMainProcess(appContext);
} Try / catch
try {
TinkerInstaller.onReceiveUpgradePatch(context, patchPath);
} catch (Throwable t) {
// upgradePatchProcessor null surfaces here as TinkerRuntimeException
reportPatchApplyFailure(t);
} Prevention
- Install tinker unconditionally in DefaultApplicationLike.onCreate for every process.
- Never gate install() on remote flags; toggle behavior with tinkerFlags/isTinkerEnabled instead.
- Ensure the :patch process manifest entry is correct so Application code runs there too.
When it happens
Trigger: TinkerPatchService.onHandleIntent receives a valid apply intent, but Tinker.install(context, ...) (or TinkerInstaller.install) has not executed in this process — because install was skipped, thrown earlier, or the service runs in a process whose Application path never installs tinker.
Common situations: The :patch process was started (e.g., by a sticky redelivery or an app-external component) before Application.onCreate ran install; a conditional install (only when a server flag is set) leaves tinker uninstalled while a patch intent arrives; install threw earlier and the app caught it, leaving the service unconfigured.
Related errors
- you must install tinker before get tinker sInstance
- you must install tinker before get tinker sInstance
- Tinker instance is already set.
- resultServiceClass is null.
- getPatchPathExtra, but intent is null
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/3ba9dc6301cce14b.
Report an issue: GitHub.