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

  1. Check the ticket id being requested — confirm it has a valid CAS prefix and is not truncated or URL-decoded incorrectly.
  2. Verify the TicketCatalog registers definitions for all ticket prefixes present in the shared Hazelcast cluster (especially custom tickets).
  3. If old tickets use legacy prefixes, flush the shared map or register compatibility definitions.
  4. 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

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


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)