wuyouzhuguli/SpringAll · warning · ValidateCodeException
验证码不存在!
Error message
验证码不存在!
What it means
Thrown by ValidateCodeFilter.validateCode when the session contains no ImageCode under key ValidateController.SESSION_KEY_IMAGE_CODE ("SESSION_KEY_IMAGE_CODE"). It means the server never generated/stored a captcha for this session, or the session was lost. Raised as a ValidateCodeException and routed to AuthenticationFailureHandler.
Source
Thrown at 59.Spring-Security-SessionManager/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java:51
try {
validateCode(new ServletWebRequest(httpServletRequest));
} catch (ValidateCodeException e) {
authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
return;
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
private void validateCode(ServletWebRequest servletWebRequest) throws ServletRequestBindingException {
ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
String codeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "imageCode");
if (StringUtils.isBlank(codeInRequest)) {
throw new ValidateCodeException("验证码不能为空!");
}
if (codeInSession == null) {
throw new ValidateCodeException("验证码不存在!");
}
if (codeInSession.isExpire()) {
sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
throw new ValidateCodeException("验证码已过期!");
}
if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)) {
throw new ValidateCodeException("验证码不正确!");
}
sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
}
}
View on GitHub (pinned to 614d2578d9)
Solutions
- Guarantee the login page always loads GET /code/image (which stores ImageCode in session) before the user submits /login.
- Confirm JSESSIONID is preserved across the image fetch and the login POST (same-origin, cookies enabled).
- Check the createCode path in ValidateController actually runs and stores under SESSION_KEY_IMAGE_CODE.
- Enable sticky sessions or a shared session store behind a load balancer.
Example fix
// before
// user submits /login directly without loading the captcha image
// after
// page onload:
fetch('/code/image').then(() => { /* enable submit */ }); Defensive patterns
Strategy: validation
Validate before calling
// client-side: load captcha image first, then enable login
fetch('/code/image').then(() => { document.getElementById('submit').disabled = false; }); Try / catch
// rely on AuthenticationFailureHandler; treat missing-session as '请先获取验证码'
Prevention
- Always fetch /code/image on page load.
- Keep JSESSIONID consistent (same-origin, cookies on).
- Use sticky sessions behind a load balancer.
When it happens
Trigger: A POST /login arrives without a prior GET /code/image in the same JSESSIONID; the user opened the login page in a fresh tab/cookieless context; the session expired between fetching the image and submitting; or the image endpoint failed so nothing was stored.
Common situations: Client does not call /code/image before submitting; browser cookies blocked so each request is a new session; reverse proxy/load balancer without sticky sessions; session store flushed on redeploy.
Related errors
AI-assisted analysis of wuyouzhuguli/SpringAll@614d2578d9 (2026-08-14).
Data as JSON: /api/errors/836c5dd830f66710.
Report an issue: GitHub.