apereo/cas · warning

Recaptcha response/token is missing from the request

Error message

Recaptcha response/token is missing from the request

What it means

ValidateCaptchaAction logs this warning when the HTTP request contains no reCAPTCHA response token (the 'g-recaptcha-response' parameter), so there is nothing to verify. The action returns the error event, failing the CAPTCHA portion of the flow.

Solutions

  1. Ensure the login page renders the reCAPTCHA widget and the g-recaptcha-response field is included in the POST.
  2. Check browser console for JavaScript failures (blocked google.com/recaptcha scripts, CSP issues).
  3. If integration tests or headless clients are involved, either obtain a valid test token or bypass the captcha feature for that environment.
  4. Confirm the correct request parameter name is being posted for the configured validator.

Example fix

<!-- before: form missing captcha field -->
<input name="username"/>
<!-- after -->
<div class="g-recaptcha" th:attr="data-sitekey=${siteKey}"></div>
Defensive patterns

Strategy: validation

Validate before calling

// before submitting the login form
grecaptcha.ready(() => grecaptcha.execute(siteKey, {action: 'login'}).then(token => {
  if (!token) throw new Error('recaptcha token missing');
  form.append('g-recaptcha-response', token);
}));

Type guard

function hasRecaptchaToken(params: URLSearchParams): boolean {
  return (params.get('g-recaptcha-response') ?? '').trim().length > 0;
}

Try / catch

Event e = validateCaptchaAction.execute(requestContext);
if (CasWebflowConstants.TRANSITION_ID_ERROR.equals(e.getId())) {
  LOGGER.warn("CAPTCHA validation error; prompting user to retry");
  modelAndView.setViewName("captcha-retry");
}

Prevention

When it happens

Trigger: doExecuteInternal calls captchaValidator.getRecaptchaResponse(request) which returns blank because the browser/client did not submit the g-recaptcha-response parameter (widget not rendered, JS disabled, form field missing, or token already consumed).

Common situations: Frontend missing the reCAPTCHA widget or not wiring g-recaptcha-response into the submitted form; JavaScript errors preventing token generation; automated clients posting directly to the endpoint without a token; tokens consumed by a prior submit.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/6e055cd5ffe2cd3c. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-captcha-core/src/main/java/org/apereo/cas/web/flow/ValidateCaptchaAction.java:40

@Slf4j
@RequiredArgsConstructor
public class ValidateCaptchaAction extends BaseCasWebflowAction {
    private final CaptchaValidator captchaValidator;

    private final CaptchaActivationStrategy captchaActivationStrategy;

    @Override
    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) {
        if (captchaActivationStrategy.shouldActivate(requestContext, captchaValidator.getRecaptchaProperties()).isEmpty()) {
            LOGGER.debug("Recaptcha is not set to activate for the current request");
            return null;
        }

        val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
        val userAgent = WebUtils.getHttpServletRequestUserAgentFromRequestContext(requestContext);
        val gRecaptchaResponse = captchaValidator.getRecaptchaResponse(request);
        if (StringUtils.isBlank(gRecaptchaResponse)) {
            LOGGER.warn("Recaptcha response/token is missing from the request");
            return getError(requestContext);
        }
        val result = captchaValidator.validate(gRecaptchaResponse, userAgent);
        if (result) {
            LOGGER.debug("Recaptcha has successfully validated the request");
            return null;
        }
        return getError(requestContext);
    }

    private Event getError(final RequestContext requestContext) {
        WebUtils.addErrorMessageToContext(requestContext, CasWebflowConstants.TRANSITION_ID_CAPTCHA_ERROR,
            CasWebflowConstants.TRANSITION_ID_CAPTCHA_ERROR);
        return getEventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_CAPTCHA_ERROR);
    }
}

View on GitHub (pinned to e7288fc434)