{"record":{"id":"0db429799ff91108","repo":"dromara/Sa-Token","slug":"account-session-loginid","errorCode":null,"errorMessage":"Account-Session 获取失败：loginId 不能为空","messagePattern":"Account-Session 获取失败：loginId 不能为空","errorType":"exception","errorClass":"SaTokenException","httpStatus":null,"severity":"error","filePath":"sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java","lineNumber":1428,"sourceCode":"\t *\n\t * @param sessionId SessionId\n\t * @return Session对象\n\t */\n\tpublic SaSession getSessionBySessionId(String sessionId) {\n\t\treturn getSessionBySessionId(sessionId, false, null, null);\n\t}\n\n\t/**\n\t * 获取指定账号 id 的 Account-Session, 如果该 SaSession 尚未创建，isCreate=是否新建并返回\n\t *\n\t * @param loginId 账号id\n\t * @param isCreate 是否新建\n\t * @param timeout 如果这个 SaSession 是新建的，则使用此值作为过期值（单位：秒），可填 null，代表使用全局 timeout 值\n\t * @return SaSession 对象\n\t */\n\tpublic SaSession getSessionByLoginId(Object loginId, boolean isCreate, Long timeout) {\n\t\tif(SaFoxUtil.isEmpty(loginId)) {\n\t\t\tthrow new SaTokenException(\"Account-Session 获取失败：loginId 不能为空\");\n\t\t}\n\t\treturn getSessionBySessionId(splicingKeySession(loginId), isCreate, timeout, session -> {\n\t\t\t// 这里是该 Account-Session 首次创建时才会被执行的方法：\n\t\t\t// \t\t设定这个 SaSession 的各种基础信息：类型、账号体系、账号id\n\t\t\tsession.setType(SaTokenConsts.SESSION_TYPE__ACCOUNT);\n\t\t\tsession.setLoginType(getLoginType());\n\t\t\tsession.setLoginId(loginId);\n\t\t});\n\t}\n\n\t/**\n\t * 获取指定账号 id 的 Account-Session, 如果该 SaSession 尚未创建，isCreate=是否新建并返回\n\t *\n\t * @param loginId 账号id\n\t * @param isCreate 是否新建\n\t * @return SaSession 对象\n\t */\n\tpublic SaSession getSessionByLoginId(Object loginId, boolean isCreate) {","sourceCodeStart":1410,"sourceCodeEnd":1446,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java#L1410-L1446","documentation":"Thrown by StpLogic.getSessionByLoginId when loginId is null or empty. The Account-Session key is derived from loginId (satoken:login:session:{loginType}:{loginId}), so an empty id cannot map to any session. It is a defensive guard against programmer error, not a runtime state problem.","triggerScenarios":"Calling getSessionByLoginId(null, ...) or getSessionByLoginId(\"\", ...) — often indirectly via StpUtil.getSession() when not logged in and getLoginId() returned null, or via getSessionByLoginId(request.getParameter(\"uid\")) with a missing parameter.","commonSituations":"Invoking StpUtil.getSession() in a route not guarded by login check; passing a numeric id that was never set (Long null unboxed/unprinted as 'null'); session-related code run in async threads where the request context is absent.","solutions":["Guard with isLogin() (or checkLogin()) before calling StpUtil.getSession() / getSessionByLoginId in request-scoped code.","If the loginId originates from user input or a nullable field, validate it is non-empty before the call.","In background threads, pass the loginId explicitly from the originating request instead of relying on context.","Verify the token configuration (token-name, token-prefix, is-read-cookie/header) so the loginId can actually be resolved."],"exampleFix":"// before\nSaSession session = StpUtil.getSessionByLoginId(userId, true);\n\n// after\nif (SaFoxUtil.isEmpty(userId)) {\n    throw new IllegalArgumentException(\"userId required\");\n}\nSaSession session = StpUtil.getSessionByLoginId(userId, true);","handlingStrategy":"validation","validationCode":"StpUtil.checkLogin(); // guarantees a resolvable loginId in request context\nSaSession s = StpUtil.getSession();","typeGuard":"Object loginId = StpUtil.getLoginIdDefaultNull();\nboolean hasLoginId = loginId != null && !String.valueOf(loginId).isEmpty();","tryCatchPattern":null,"preventionTips":["Guard session access behind login checks","Pass explicit loginIds into background jobs instead of relying on request context","Validate nullable user ids at the controller boundary"],"tags":["session","login-id","validation"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}