apereo/cas · warning
No ticket definition could be found in the catalog to match
Error message
No ticket definition could be found in the catalog to match [{}] What it means
HazelcastTicketRegistry.getTicket logs this warning and returns null when the TicketCatalog contains no TicketDefinition whose prefix matches the given ticket id. Without a definition, the registry cannot determine which Hazelcast map to query, so the lookup can never succeed. Callers will typically see this as 'ticket not found' / SSO redirect to login.
Solutions
- Check the ticket id being requested — confirm it has a valid CAS prefix and is not truncated or URL-decoded incorrectly.
- Verify the TicketCatalog registers definitions for all ticket prefixes present in the shared Hazelcast cluster (especially custom tickets).
- If old tickets use legacy prefixes, flush the shared map or register compatibility definitions.
- Ensure all CAS nodes behind the shared registry run the same ticket catalog configuration.
Example fix
// before
String ticketId = request.getParameter("ticket").substring(0, 20); // truncated
// after
String ticketId = request.getParameter("ticket"); // pass the full id intact Defensive patterns
Strategy: type-guard
Validate before calling
// Check the ticket id has a known prefix before calling getTicket
var prefixes = ticketCatalog.findAllStream().map(d -> d.getProperties().getPrefix()).toList();
if (prefixes.stream().noneMatch(ticketId::startsWith)) {
logger.warn("Ignoring ticket id {} with unknown prefix", ticketId);
return null;
} Type guard
boolean isKnownTicketId(String ticketId) {
return ticketId != null && ticketCatalog.findAllStream()
.anyMatch(d -> ticketId.startsWith(d.getProperties().getPrefix()));
} Prevention
- Never truncate or transform ticket ids between receipt and registry lookup.
- Keep TicketCatalog definitions identical across all CAS nodes sharing a Hazelcast cluster.
- Clean legacy ticket maps after version upgrades if prefixes changed.
- Validate incoming ticket ids against known prefixes before hitting the registry.
When it happens
Trigger: getTicket(ticketId) with an id whose prefix (e.g. 'TGT-', 'ST-', 'PT-') matches no registered TicketDefinition — malformed/truncated ticket ids, tickets from an older CAS version with different prefixes, or custom ticket types whose definitions were never registered in the catalog.
Common situations: Client presents a corrupted or hand-crafted ticket id; CAS upgraded and ticket id prefixes changed while old tickets persist in shared Hazelcast; multiple CAS instances with different TicketCatalogs sharing one Hazelcast cluster; passing a full ticket object's wrong field (e.g. encoded id without prefix).
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Unable to locate ticket map for ticket metadata
- Final ticket id [ ] length [ ] exceeds [ ] characters
- Ticket passed is null and cannot be decoded
- Service ticket [ ] does not exist.
- Service ticket [ ] is not assigned a valid ticket granting…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/4c84749c7a02885c.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-hazelcast-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/HazelcastTicketRegistry.java:122
return null;
}
val metadata = ticketCatalog.find(ticketId);
if (metadata != null) {
val map = getTicketMapInstanceByMetadata(metadata);
if (map != null) {
val document = map.get(encTicketId);
if (document != null && document.getTicket() != null) {
val result = decodeTicket(document.getTicket());
if (predicate != null && predicate.test(result)) {
return result;
}
}
return null;
} else {
LOGGER.error("Unable to locate ticket map for ticket definition [{}]", metadata);
}
}
LOGGER.warn("No ticket definition could be found in the catalog to match [{}]", ticketId);
return null;
}
@Override
public long deleteSingleTicket(final Ticket ticketToDelete) {
val encTicketId = digestIdentifier(ticketToDelete.getId());
val metadata = ticketCatalog.find(ticketToDelete);
val map = getTicketMapInstanceByMetadata(metadata);
return map != null && map.remove(encTicketId) != null ? 1 : 0;
}
@Override
public long deleteAll() {
return ticketCatalog.findAll()
.stream()
.map(this::getTicketMapInstanceByMetadata)
.filter(Objects::nonNull)
.mapToInt(instance -> {View on GitHub (pinned to e7288fc434)