{"record":{"id":"a3a45f58898340b6","repo":"qiurunze123/miaosha","slug":"10001","errorCode":"10001","errorMessage":"系统错误","messagePattern":"系统错误","errorType":"exception","errorClass":"GlobleException","httpStatus":null,"severity":"error","filePath":"miaosha-v1/src/main/java/com/geekq/miaosha/service/MiaoShaUserService.java","lineNumber":114,"sourceCode":"        try {\n            miaoShaUserDao.insertMiaoShaUser(miaoShaUser);\n            MiaoshaUser user = miaoShaUserDao.getByNickname(miaoShaUser.getNickname());\n            if (user == null) {\n                return false;\n            }\n            //生成cookie 将session返回游览器 分布式session\n            String token = UUIDUtil.uuid();\n            addCookie(response, token, user);\n        } catch (Exception e) {\n            logger.error(\"注册失败\", e);\n            return false;\n        }\n        return true;\n    }\n\n    public boolean login(HttpServletResponse response, LoginVo loginVo) {\n        if (loginVo == null) {\n            throw new GlobleException(SYSTEM_ERROR);\n        }\n\n        String mobile = loginVo.getMobile();\n        String password = loginVo.getPassword();\n        MiaoshaUser user = getByNickName(mobile);\n        if (user == null) {\n            throw new GlobleException(MOBILE_NOT_EXIST);\n        }\n\n        String dbPass = user.getPassword();\n        String saltDb = user.getSalt();\n        String calcPass = MD5Utils.formPassToDBPass(password, saltDb);\n        if (!calcPass.equals(dbPass)) {\n            throw new GlobleException(PASSWORD_ERROR);\n        }\n        //生成cookie 将session返回游览器 分布式session\n        String token = UUIDUtil.uuid();\n        addCookie(response, token, user);","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/qiurunze123/miaosha/blob/e58017658e549b63fc4db2160d2325ccd7f8435b/miaosha-v1/src/main/java/com/geekq/miaosha/service/MiaoShaUserService.java#L96-L132","documentation":"Thrown by MiaoShaUserService.login() (miaosha-v1) when the LoginVo argument is null. Maps to ResultStatus.SYSTEM_ERROR (code 10001, '系统错误' — 'System error'). This is a defensive null-check at the top of login(): a null LoginVo means the caller (typically a controller) failed to bind the request body, which is a programming or request-parsing error, not a user credential problem.","triggerScenarios":"Calling login(response, null) directly, or a controller endpoint that passes an unbound/null LoginVo because the @ModelAttribute or @RequestBody mapping failed silently. Also occurs in unit tests that call login() without constructing a LoginVo.","commonSituations":"The login JSON body is malformed so Spring fails to deserialize LoginVo and the controller still invokes the service with null; a missing @Valid annotation lets an empty body through; integration test forgetting to populate the LoginVo.","solutions":["Add @Valid on the LoginVo parameter in the controller so Spring rejects null/malformed bodies before reaching the service.","Return a 400 Bad Request from the controller when loginVo is null instead of calling the service.","In tests, always construct a LoginVo with setMobile() and setPassword() before calling login()."],"exampleFix":"// before\npublic boolean login(HttpServletResponse response, LoginVo loginVo) {\n    if (loginVo == null) {\n        throw new GlobleException(SYSTEM_ERROR);\n    }\n    ...\n}\n\n// after — controller validates, service trusts input\n@PostMapping(\"/do_login\")\npublic ResultGeekQ<Boolean> doLogin(@RequestBody @Valid LoginVo loginVo,\n                                    HttpServletResponse response) {\n    return ResultGeekQ.build().setData(userService.login(response, loginVo));\n}","handlingStrategy":"validation","validationCode":"// Controller-layer null check before calling login()\nif (loginVo == null) {\n    return ResultGeekQ.error(ResultStatus.PARAM_ERROR);\n}\nreturn userService.login(response, loginVo);","typeGuard":"// Ensure LoginVo is properly constructed before passing to login()\nLoginVo vo = new LoginVo();\nvo.setMobile(mobile);\nvo.setPassword(password);\n// type guard: both fields non-null and non-empty\nif (vo.getMobile() == null || vo.getPassword() == null) {\n    throw new IllegalArgumentException(\"LoginVo fields must not be null\");\n}","tryCatchPattern":"try {\n    userService.login(response, loginVo);\n} catch (GlobleException e) {\n    if (e.getStatus() == ResultStatus.SYSTEM_ERROR) {\n        return ResultGeekQ.error(ResultStatus.PARAM_ERROR);\n    }\n    throw e;\n}","preventionTips":["Add @Valid on the LoginVo controller parameter so Spring rejects null bodies with a 400.","Always populate both mobile and password fields in test code.","Use @NotNull JSR-303 annotations on LoginVo fields to catch binding failures early."],"tags":["authentication","null-check","input-validation","miaosha-v1","system-error"],"backgroundTag":null,"analyzedSha":"e58017658e549b63fc4db2160d2325ccd7f8435b","analyzedAt":"2026-08-14T05:22:03.691Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}