{"record":{"id":"9992ccf3f4447106","repo":"dromara/Sa-Token","slug":"10031","errorCode":"10031","errorMessage":"重置的侦听器集合不可以为空","messagePattern":"重置的侦听器集合不可以为空","errorType":"validation","errorClass":"SaTokenException","httpStatus":null,"severity":"error","filePath":"sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java","lineNumber":61,"sourceCode":"\t\t// 默认添加控制台日志侦听器 \n\t\tlistenerList.add(new SaTokenListenerForLog());\n\t}\n\n\t/**\n\t * 获取已注册的所有侦听器\n\t * @return / \n\t */\n\tpublic static List<SaTokenListener> getListenerList() {\n\t\treturn listenerList;\n\t}\n\n\t/**\n\t * 重置侦听器集合\n\t * @param listenerList / \n\t */\n\tpublic static void setListenerList(List<SaTokenListener> listenerList) {\n\t\tif(listenerList == null) {\n\t\t\tthrow new SaTokenException(\"重置的侦听器集合不可以为空\").setCode(SaErrorCode.CODE_10031);\n\t\t}\n\t\tSaTokenEventCenter.listenerList = listenerList;\n\t}\n\n\t/**\n\t * 注册一个侦听器 \n\t * @param listener / \n\t */\n\tpublic static void registerListener(SaTokenListener listener) {\n\t\tif(listener == null) {\n\t\t\tthrow new SaTokenException(\"注册的侦听器不可以为空\").setCode(SaErrorCode.CODE_10032);\n\t\t}\n\t\tlistenerList.add(listener);\n\t}\n\n\t/**\n\t * 注册一组侦听器 \n\t * @param listenerList / ","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java#L43-L79","documentation":"SaTokenException (code 10031) thrown by SaTokenEventCenter.setListenerList(List<SaTokenListener>) when the supplied list is null. The event center dispatches login/logout/token lifecycle events to its listener list, so replacing it with null would break all event notification — the null check guards that invariant before assignment.","triggerScenarios":"Calling SaTokenEventCenter.setListenerList(null) directly, typically from custom framework-integration code or startup customization that builds a listener list and passes a null reference (e.g. a field that was never initialized, or a conditional that yields null).","commonSituations":"Custom integrations or migration code that swaps the listener list at runtime; a list variable conditionally initialized and null in some environment; copy-pasted setup code where the list construction was removed but the setListenerList call remained.","solutions":["Pass a non-null list; to clear all listeners use an empty list: SaTokenEventCenter.setListenerList(new ArrayList<>())","Fix the upstream initialization so the variable can never be null at the call site","Prefer the additive API registerListener(...) / registerListenerList(...) instead of replacing the whole list"],"exampleFix":"// before\nList<SaTokenListener> listeners = maybeNull();\nSaTokenEventCenter.setListenerList(listeners); // NPE-guard -> exception 10031\n\n// after\nSaTokenEventCenter.setListenerList(\n    listeners != null ? listeners : new ArrayList<>());","handlingStrategy":"validation","validationCode":"if (listenerList == null) { /* do not call setListenerList; build an empty list instead */ }\nSaTokenEventCenter.setListenerList(listenerList != null ? listenerList : new ArrayList<>());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use empty collections instead of null when 'no listeners' is the intent","Prefer registerListener/registerListenerList over replacing the whole list","Ensure collector methods never return null (Collections.emptyList() convention)"],"tags":["event-listener","validation","null-safety","sa-token"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}