FriendlyCaptchaException.java
package org.drjekyll.friendlycaptcha;
import java.io.Serial;
import lombok.Getter;
import org.jspecify.annotations.Nullable;
/**
* Thrown when the Friendly Captcha API returns an error response, when the response cannot be
* parsed, or when a network-level failure prevents verification from completing.
*
* <p>Callers should distinguish this from a plain {@code false} return value: a {@code false} means
* the solution was rejected (invalid, expired, or already used), while this exception means the
* verification request itself failed.
*
* <p>{@link #getStatusCode()} returns the HTTP status code when the API responded with an error, or
* {@code null} for non-HTTP failures (network errors, unreadable responses, invalid configuration).
* {@link #getErrorCode()} returns the machine-readable error code when the API included one in its
* response body.
*/
@Getter
public class FriendlyCaptchaException extends RuntimeException {
@Serial private static final long serialVersionUID = -2643367447029255633L;
/**
* The HTTP status code returned by the verification API, or {@code null} if the exception was not
* caused by an HTTP response (e.g. a network error or invalid configuration).
*/
@Nullable private final Integer statusCode;
/**
* The machine-readable error code included in the API response body, or {@code null} if the API
* did not return one or the exception was not caused by an API error response.
*/
@Nullable private final ErrorCode errorCode;
FriendlyCaptchaException(@Nullable String message) {
this(message, null, null, null);
}
FriendlyCaptchaException(@Nullable String message, @Nullable Throwable cause) {
this(message, null, null, cause);
}
FriendlyCaptchaException(@Nullable String message, int statusCode) {
this(message, statusCode, null, null);
}
FriendlyCaptchaException(
@Nullable String message, int statusCode, @Nullable ErrorCode errorCode) {
this(message, statusCode, errorCode, null);
}
FriendlyCaptchaException(
@Nullable String message,
int statusCode,
@Nullable ErrorCode errorCode,
@Nullable Throwable cause) {
this(message, Integer.valueOf(statusCode), errorCode, cause);
}
private FriendlyCaptchaException(
String message,
@Nullable Integer statusCode,
@Nullable ErrorCode errorCode,
@Nullable Throwable cause) {
super(message, cause);
this.statusCode = statusCode;
this.errorCode = errorCode;
}
}