{"record":{"id":"3ba9dc6301cce14b","repo":"Tencent/tinker","slug":"upgradepatchprocessor-is-null","errorCode":null,"errorMessage":"upgradePatchProcessor is null.","messagePattern":"upgradePatchProcessor is null\\.","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"critical","filePath":"tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/service/TinkerPatchService.java","lineNumber":236,"sourceCode":"            }\n            String path = getPatchPathExtra(intent);\n            if (path == null) {\n                ShareTinkerLog.e(TAG, \"TinkerPatchService can't get the path extra, ignoring.\");\n                return;\n            }\n            File patchFile = new File(path);\n\n            final boolean useEmergencyMode = getPatchUseEmergencyMode(intent);\n\n            long begin = SystemClock.elapsedRealtime();\n            boolean result;\n            long cost;\n            Throwable e = null;\n\n            PatchResult patchResult = new PatchResult();\n            try {\n                if (upgradePatchProcessor == null) {\n                    throw new TinkerRuntimeException(\"upgradePatchProcessor is null.\");\n                }\n                result = upgradePatchProcessor.tryPatch(context, path, useEmergencyMode, patchResult);\n            } catch (Throwable throwable) {\n                e = throwable;\n                result = false;\n                tinker.getPatchReporter().onPatchException(patchFile, e);\n            }\n\n            cost = SystemClock.elapsedRealtime() - begin;\n            tinker.getPatchReporter()\n                    .onPatchResult(patchFile, result, cost);\n\n            patchResult.isSuccess = result;\n            patchResult.rawPatchFilePath = path;\n            patchResult.useEmergencyMode = useEmergencyMode;\n            patchResult.totalCostTime = cost;\n            patchResult.type = tinker.getCustomPatcher() == null ? PatchResult.PATCH_TYPE_BSDIFF : PatchResult.PATCH_TYPE_CUSTOM;\n            patchResult.e = e;","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/service/TinkerPatchService.java#L218-L254","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (remoteConfig.tinkerEnabled) {\n    TinkerInstaller.install(appLike);\n}\n\n// after\nTinkerInstaller.install(appLike); // always install; control enablement via tinkerFlags/isTinkerEnabled instead","handlingStrategy":"validation","validationCode":"if (!Tinker.isTinkerInstalled()) {\n    // cannot apply patches yet: defer instead of starting the service\n    deferPatchWorkUntilInstall();\n    return;\n}\nTinkerInstaller.onReceiveUpgradePatch(context, patchPath);","typeGuard":"public static boolean canApplyPatches() {\n    return Tinker.isTinkerInstalled()\n        && Tinker.isTinkerEnabled()\n        && TinkerServiceInternals.isInMainProcess(appContext);\n}","tryCatchPattern":"try {\n    TinkerInstaller.onReceiveUpgradePatch(context, patchPath);\n} catch (Throwable t) {\n    // upgradePatchProcessor null surfaces here as TinkerRuntimeException\n    reportPatchApplyFailure(t);\n}","preventionTips":["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."],"tags":["tinker","android","initialization","service","ordering"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}