{"record":{"id":"090462f507fc3183","repo":"fish2018/pansou","slug":"token-cannot-be-empty","errorCode":null,"errorMessage":"token cannot be empty","messagePattern":"token cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/jwt.go","lineNumber":42,"sourceCode":"\n\texpirationTime := time.Now().Add(expiry)\n\tclaims := &Claims{\n\t\tUsername: username,\n\t\tRegisteredClaims: jwt.RegisteredClaims{\n\t\t\tExpiresAt: jwt.NewNumericDate(expirationTime),\n\t\t\tIssuedAt:  jwt.NewNumericDate(time.Now()),\n\t\t\tIssuer:    \"pansou\",\n\t\t},\n\t}\n\n\ttoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\n\treturn token.SignedString([]byte(secret))\n}\n\n// ValidateToken 验证JWT token\nfunc ValidateToken(tokenString string, secret string) (*Claims, error) {\n\tif tokenString == \"\" {\n\t\treturn nil, errors.New(\"token cannot be empty\")\n\t}\n\tif secret == \"\" {\n\t\treturn nil, errors.New(\"secret cannot be empty\")\n\t}\n\n\tclaims := &Claims{}\n\n\ttoken, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {\n\t\t// 验证签名算法\n\t\tif _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {\n\t\t\treturn nil, errors.New(\"unexpected signing method\")\n\t\t}\n\t\treturn []byte(secret), nil\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/util/jwt.go#L24-L60","documentation":"Sentinel validation error at the top of ValidateToken (util/jwt.go:42): raised when the token string argument is empty, meaning there is nothing to parse or verify. It indicates the caller passed a missing/blank credential (e.g. no Authorization header) rather than an invalid or expired token.","triggerScenarios":"请求未携带 Authorization 头、Bearer 后为空串，或上游中间件在鉴权前就把空 token 传入校验函数。","commonSituations":"Client sends no Authorization header; header uses wrong scheme so prefix trimming yields empty string; token dropped by a proxy.","solutions":["Check auth middleware: return 401 when the extracted token string is empty before calling ValidateToken","Ensure clients send \"Authorization: Bearer <token>\" and the middleware parses the prefix correctly","On the client, never send requests to protected endpoints without storing/attaching the token"],"exampleFix":"// before\nclaims, err := util.ValidateToken(tokenString, secret)\n// after\nif tokenString == \"\" {\n    c.AbortWithStatusJSON(401, gin.H{\"error\": \"missing token\"})\n    return\n}\nclaims, err := util.ValidateToken(tokenString, secret)","handlingStrategy":"validation","validationCode":"if tokenString == \"\" { return errors.New(\"missing bearer token\") }","typeGuard":null,"tryCatchPattern":"claims, err := util.ValidateToken(tokenString, secret)\nif err != nil {\n    c.AbortWithStatusJSON(401, gin.H{\"error\": \"unauthorized\"})\n    return\n}","preventionTips":["Reject requests missing Authorization header in middleware","Parse the Bearer prefix defensively","Return 401 (not 500) for missing tokens"],"tags":["jwt","validation","go","authentication"],"backgroundTag":"empty-required-field","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}