{"record":{"id":"67a1bb5b0fab78d0","repo":"Tencent/matrix","slug":"closer-null","errorCode":null,"errorMessage":"closer == null","messagePattern":"closer == null","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-io-canary/src/main/java/com/tencent/matrix/iocanary/detect/MatrixCloseGuard.java","lineNumber":179,"sourceCode":"        return sREPORTER;\n    }\n\n    private MatrixCloseGuard() {\n    }\n\n    /**\n     * If CloseGuard is enabled, {@code open} initializes the instance\n     * with a warning that the caller should have explicitly called the\n     * {@code closer} method instead of relying on finalization.\n     *\n     * @param closer non-null name of explicit termination method\n     * @throws NullPointerException if closer is null, regardless of\n     *                              whether or not CloseGuard is enabled\n     */\n    public void open(String closer) {\n        // always perform the check for valid API usage...\n        if (closer == null) {\n            throw new NullPointerException(\"closer == null\");\n        }\n        // ...but avoid allocating an allocationSite if disabled\n        if (this == NOOP || !sENABLED) {\n            return;\n        }\n        String message = \"Explicit termination method '\" + closer + \"' not called\";\n        allocationSite = new Throwable(message);\n    }\n\n    private Throwable allocationSite;\n\n    /**\n     * Marks this CloseGuard instance as closed to avoid warnings on\n     * finalization.\n     */\n    public void close() {\n        allocationSite = null;\n    }","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-io-canary/src/main/java/com/tencent/matrix/iocanary/detect/MatrixCloseGuard.java#L161-L197","documentation":"MatrixCloseGuard.open(closer) throws NullPointerException when the caller passes a null closer name. The name is used to build the 'Explicit termination method not called' leak-report message, so it must be a non-null method name like 'close()' or 'release()'. Unlike most checks here, this validation runs even when CloseGuard is disabled, so it fails fast regardless of configuration.","triggerScenarios":"Calling closeGuard.open(null) directly, or passing a variable that resolves to null (e.g. a method name looked up reflectively that returned null).","commonSituations":"Wrapping a resource class whose close-method name is derived from configuration or reflection; refactoring code that used to pass a constant string; unit tests that pass null placeholders.","solutions":["Pass a concrete non-null termination-method name to open(), e.g. open(\"close\") or open(\"release\")","If the name is computed, default it before calling: open(name != null ? name : \"close\")","Check the caller site for reflective lookups that can return null and handle the null before calling open"],"exampleFix":"// before\nguard.open(closeMethodName); // closeMethodName may be null\n// after\nguard.open(closeMethodName != null ? closeMethodName : \"close\");","handlingStrategy":"validation","validationCode":"if (closerName == null) throw new IllegalArgumentException(\"closer name required\"); guard.open(closerName);","typeGuard":"boolean isValidCloser(String s) { return s != null && !s.isEmpty(); }","tryCatchPattern":"try { guard.open(name); } catch (NullPointerException e) { log.error(\"open(null): pass a termination method name\", e); }","preventionTips":["Always pass literal method names like \"close\"/\"release\" to open()","Never source the open() argument from nullable lookups without defaulting","Assert non-null in tests that exercise CloseGuard wrappers"],"tags":["android","memory-leak","null-argument"],"backgroundTag":"null-argument","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}