{"record":{"id":"27487f0d5fe73717","repo":"dromara/Sa-Token","slug":"12002","errorCode":"12002","errorMessage":"name不能为空","messagePattern":"name不能为空","errorType":"validation","errorClass":"SaTokenException","httpStatus":null,"severity":"error","filePath":"sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaCookie.java","lineNumber":322,"sourceCode":"\n\t/**\n\t * 构建一下\n\t */\n\tpublic void builder() {\n\t\tif(path == null) {\n\t\t\tpath = \"/\";\n\t\t}\n\t}\n\n\t/**\n\t * 转换为响应头 Set-Cookie 参数需要的值\n\t * @return /\n\t */\n\tpublic String toHeaderValue() {\n\t\tthis.builder();\n\n\t\tif(SaFoxUtil.isEmpty(name)) {\n\t\t\tthrow new SaTokenException(\"name不能为空\").setCode(SaErrorCode.CODE_12002);\n\t\t}\n\t\tif(value != null && value.contains(\";\")) {\n\t\t\tthrow new SaTokenException(\"无效Value：\" + value).setCode(SaErrorCode.CODE_12003);\n\t\t}\n\n\t\t// example：\n\t\t// Set-Cookie: name=value; Max-Age=100000; Expires=Tue, 05-Oct-2021 20:28:17 GMT; Domain=localhost; Path=/; Secure; HttpOnly; SameSite=Lax\n\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(name).append(\"=\").append(value);\n\n\t\tif(maxAge >= 0) {\n\t\t\t sb.append(\"; Max-Age=\").append(maxAge);\n\t\t\t String expires;\n\t\t\t if(maxAge == 0) {\n\t\t\t\t expires = Instant.EPOCH.atOffset(ZoneOffset.UTC).format(DateTimeFormatter.RFC_1123_DATE_TIME);\n\t\t\t } else {\n\t\t\t\t expires = OffsetDateTime.now().plusSeconds(maxAge).format(DateTimeFormatter.RFC_1123_DATE_TIME);","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaCookie.java#L304-L340","documentation":"SaCookie.toHeaderValue() serializes the cookie for the Set-Cookie header and first runs builder(). If the cookie's name is null/empty at that point it throws code 12002, because a Set-Cookie line without a name is unparseable by browsers. This is a programming/config error in how the SaCookie was constructed.","triggerScenarios":"new SaCookie().setValue(\"x\").toHeaderValue(); or code that builds the token cookie from config where the token-name config item is empty (token-name= in yml/properties) and is copied into SaCookie.setName(null).","commonSituations":"Custom cookie writing in logout/login hooks that forgets setName(); an empty sa-token.token-name configuration; resetting a cookie via new SaCookie() and only setting maxAge=0 for deletion without naming it.","solutions":["Always set the name: new SaCookie().setName(StpUtil.getTokenName()).setValue(v)...","Check application config: sa-token.token-name must be non-empty (it is also the cookie name by default)","For cookie deletion, set name and maxAge=0 explicitly rather than building an anonymous cookie"],"exampleFix":"// before\nSaCookie cookie = new SaCookie().setValue(\"\").setMaxAge(0);\nSaHolder.getResponse().addCookie(cookie); // CODE_12002\n\n// after\nSaCookie cookie = new SaCookie()\n        .setName(StpUtil.getTokenName())\n        .setValue(\"\")\n        .setMaxAge(0);\nSaHolder.getResponse().addCookie(cookie);","handlingStrategy":"validation","validationCode":"if (SaFoxUtil.isEmpty(cookie.getName())) {\n    throw new IllegalArgumentException(\"SaCookie name required before toHeaderValue()\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always chain .setName(...) first when building SaCookie","Keep sa-token.token-name non-empty in config","Centralize cookie construction in one helper method"],"tags":["sa-token","cookie","validation","configuration"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}