{"record":{"id":"7b6aa815b4af970b","repo":"Tencent/tinker","slug":"listener-must-not-be-null-7b6aa8","errorCode":null,"errorMessage":"listener must not be null.","messagePattern":"listener must not be null\\.","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":408,"sourceCode":"            }\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;\n            return this;\n        }\n\n        public Tinker build() {\n            if (status == -1) {\n                status = ShareConstants.TINKER_ENABLE_ALL;\n            }\n","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java#L390-L426","documentation":"Thrown by Tinker.Builder.listener when the PatchListener argument is null. The PatchListener is the entry filter for patch requests (onPatchUnused, onPatchVersionCheck, etc.) and gates whether a downloaded patch is applied; Tinker refuses to build without one rather than silently dropping patches.","triggerScenarios":"Calling builder.listener(null) — the argument came from an uninitialized field, a factory that can return null, or a copy of the Tinker sample with the DefaultPatchListener line removed.","commonSituations":"Migrating from the sample app and dropping the listener line because 'we patch server-driven only', DI graphs missing the PatchReporter/PatchListener binding, or Kotlin code where platform-type nullability slipped through.","solutions":["Pass a non-null PatchListener such as new DefaultPatchListener(context).","If custom patch filtering is not needed, use the default listener; if it is needed, implement your own subclass and pass it.","Annotate the wiring method parameters @NonNull and enable nullness checks so the compiler catches this earlier."],"exampleFix":"// before\nbuilder.listener(null);\n\n// after\nbuilder.listener(new DefaultPatchListener(context));","handlingStrategy":"validation","validationCode":"PatchListener listener = new DefaultPatchListener(context); // always non-null\nbuilder.listener(listener);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a concrete PatchListener (default or custom) in the install chain.","Annotate helper factories that build the listener as @NonNull-returning.","Compile-time nullness annotations catch accidental nulls before runtime."],"tags":["tinker","android","builder","null-argument","patch-listener"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}