halo-dev/halo · warning · InvalidCookieException
Cookie token[1] did not contain a valid number (contained '{
Error message
Cookie token[1] did not contain a valid number (contained '{}') What it means
After Base64-decoding the remember-me cookie and splitting on the delimiter, getTokenExpiryTime() parses token slot [1] as a long (epoch millis). If Long.parseLong throws NumberFormatException, the slot is not a valid expiry timestamp and an InvalidCookieException is thrown. The expiry is the second token in the cookie payload (index 1).
Source
Thrown at application/src/main/java/run/halo/app/security/authentication/rememberme/TokenBasedRememberMeServices.java:196
throw new InvalidCookieException(
"Cookie contained signature '" + actualTokenSignature
+ "' but expected '"
+ expectedTokenSignature + "'");
}
})
.thenReturn(userDetails);
});
}
protected boolean isTokenExpired(long tokenExpiryTime) {
return tokenExpiryTime < System.currentTimeMillis();
}
private long getTokenExpiryTime(String[] cookieTokens) {
try {
return Long.parseLong(cookieTokens[1]);
} catch (NumberFormatException nfe) {
throw new InvalidCookieException(
"Cookie token[1] did not contain a valid number (contained '" + cookieTokens[1] + "')");
}
}
protected Mono<Authentication> createSuccessfulAuthentication(ServerWebExchange exchange, UserDetails user) {
return getKey().map(key -> new RememberMeAuthenticationToken(
key, user, this.authoritiesMapper.mapAuthorities(user.getAuthorities())));
}
private boolean isValidCookieTokensLength(String[] cookieTokens) {
return cookieTokens.length == 3 || cookieTokens.length == 4;
}
@Override
public Mono<Void> loginFail(ServerWebExchange exchange) {
log.debug("Interactive login attempt was unsuccessful.");
cancelCookie(exchange);
return parameterRequestCache.saveParameter(exchange, parameterName);View on GitHub (pinned to d2f5165f9c)
Solutions
- Treat it as a bad cookie: the user re-authenticates and a correctly-formatted cookie is issued (handleError cancels the cookie automatically).
- If reproducible across many users, check whether a proxy/CDN is rewriting or truncating the cookie value.
- Verify you are not running mixed Halo versions that emit different token layouts.
- Ensure the cookie is not being URL-encoded twice in transit.
Defensive patterns
Strategy: try-catch
Try / catch
// Rely on TokenBasedRememberMeServices.handleError which cancels the cookie:
.onErrorResume(InvalidCookieException.class, ex -> {
log.debug("Malformed remember-me cookie rejected: {}", ex.getMessage());
return Mono.empty();
}) Prevention
- Do not manually edit or truncate remember-me cookie values.
- Ensure reverse proxies do not rewrite or trim the cookie payload.
- Run a single Halo version across nodes so the token layout is consistent.
- Treat any InvalidCookieException as a recoverable 'please log in again' condition.
When it happens
Trigger: A remember-me cookie whose decoded second colon-delimited token is non-numeric: a truncated, tampered, or manually-constructed cookie; a cookie produced by an incompatible/older cookie format; URL-decoding (URLDecoder.decode on each token) mangling the value. Reached via processAutoLoginCookie -> getTokenExpiryTime.
Common situations: Cookie altered by a browser extension or proxy; copy-paste of a cookie between users; downgrade/upgrade across a version that changed the token layout; locale-specific characters surviving into the token.
Related errors
- Cannot resolve shared dependency ${root} from ${resolutionBa
- Shared dependency ${root} resolved to ${packageJson.name ||
- Cookie contained signature '{}' but expected '{}'
- Cookie token was not Base64 encoded; value was '{}'
- Unsupported URL protocol: {}
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/0ad8ecf8baec0ce8.
Report an issue: GitHub.