{"record":{"id":"e236b711558914f5","repo":"Tencent/tinker","slug":"patchreporter-is-already-set-e236b7","errorCode":null,"errorMessage":"patchReporter is already set.","messagePattern":"patchReporter is already set\\.","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java","lineNumber":400,"sourceCode":"        }\n\n        public Builder loadReport(LoadReporter loadReporter) {\n            if (loadReporter == null) {\n                throw new TinkerRuntimeException(\"loadReporter must not be null.\");\n            }\n            if (this.loadReporter != null) {\n                throw new TinkerRuntimeException(\"loadReporter is already set.\");\n            }\n            this.loadReporter = loadReporter;\n            return this;\n        }\n\n        public Builder patchReporter(PatchReporter patchReporter) {\n            if (patchReporter == null) {\n                throw new TinkerRuntimeException(\"patchReporter must not be null.\");\n            }\n            if (this.patchReporter != null) {\n                throw new TinkerRuntimeException(\"patchReporter is already set.\");\n            }\n            this.patchReporter = patchReporter;\n            return this;\n        }\n\n        public Builder listener(PatchListener listener) {\n            if (listener == null) {\n                throw new TinkerRuntimeException(\"listener must not be null.\");\n            }\n            if (this.listener != null) {\n                throw new TinkerRuntimeException(\"listener is already set.\");\n            }\n            this.listener = listener;\n            return this;\n        }\n\n        public Builder customPatcher(AbstractFilePatch patcher) {\n            this.patcher = patcher;","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java#L382-L418","documentation":"Thrown by Tinker.Builder.patchReporter when a PatchReporter was already set on the same Builder. Like the other collaborators, Tinker allows exactly one patch reporter so patch-apply events have an unambiguous target. A second call means initialization code ran twice.","triggerScenarios":"Two sequential builder.patchReporter(...) calls on one Builder — commonly when the Builder is a static/singleton and both the app and an SDK module configure it, or when install logic sits in a method invoked from multiple lifecycle paths.","commonSituations":"SDK integrations where a third-party library also initializes Tinker, multi-process code that accidentally shares the Builder, or a hot-restart of an Activity triggering Application.onCreate-style init a second time on a retained Builder.","solutions":["Centralize Tinker initialization in one place (usually ApplicationLike#onCreate) and set the patch reporter only there.","If an SDK also initializes Tinker, coordinate on who owns the install or check Tinker.isTinkerInstalled() before configuring.","Do not cache the Builder in a static field that survives re-entry; create it fresh inside the install path."],"exampleFix":"// before\nbuilder.patchReport(new DefaultPatchReporter(context));\nbuilder.patchReport(new SdkPatchReporter(context)); // throws\n\n// after\nbuilder.patchReport(new CompositePatchReporter(context, Arrays.asList(new DefaultPatchReporter(context), new SdkPatchReporter(context))));","handlingStrategy":"validation","validationCode":"if (!Tinker.isTinkerInstalled()) {\n    Tinker.install(new Tinker.Builder(app)\n        .patchReport(new DefaultPatchReporter(app))\n        .build());\n} // second call never happens because install is idempotent-guarded","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Own Tinker initialization in exactly one class; other modules read Tinker.with(app) instead of reconfiguring.","Wrap install in an isTinkerInstalled() guard to survive multi-entry startup.","If two reporters are needed, compose them into one PatchReporter implementation."],"tags":["tinker","android","builder","double-init","patch-reporter"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}