apereo/cas · warning

Unable to locate ticket map for ticket metadata

Error message

Unable to locate ticket map for ticket metadata [{}]

What it means

In HazelcastTicketRegistry.addSingleTicket, after resolving the ticket's TicketMetadata from the catalog, the code looks up the corresponding Hazelcast IMap ('ticket map') that should hold tickets of that type. When no map is registered/found for the metadata, the ticket is NOT stored (ticketMap.set is skipped) and a warning is logged instead. The call returns the ticket normally, so persistence is silently skipped.

Solutions

  1. Ensure every ticket type in the TicketDefinition catalog has a corresponding Hazelcast map created during registry initialization.
  2. Check the ticket's metadata (prefix/name) against the configured map names in the Hazelcast ticket registry configuration.
  3. If using a custom ticket, register its definition and map in the catalog (TicketCatalogConfigurer) before use.
  4. Enable debug logging to inspect the metadata values being looked up and compare with initialized maps.

Example fix

// before
@Bean
public TicketCatalogConfigurer customTicketCatalog() {
    return chain -> chain.register(new TicketDefinition()) /* missing map registration */;
}
// after — also register the backing map for the definition
@Bean
public HazelcastTicketRegistryConfigurer hazelcastMaps() {
    return hz -> hz.getMap("customTicketMap");
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a map exists for the ticket type before adding
var metadata = ticketCatalog.findTicketDefinition(ticket).map(TicketDefinition::getProperties);
var mapName = ticketCatalog.findTicketDefinition(ticket)
    .map(d -> d.getProperties().getStorageName()).orElse(null);
if (mapName == null || hzInstance.getMap(mapName) == null) {
    throw new IllegalStateException("No Hazelcast map registered for ticket type " + ticket.getId());
}

Type guard

TicketDefinition def = ticketCatalog.findTicketDefinition(ticketId);
boolean hasMap = def != null && def.getProperties() != null && def.getProperties().getStorageName() != null;

Prevention

When it happens

Trigger: addSingleTicket(ticket) when TicketDefinition catalog contains the ticket type (metadata resolved) but there is no Hazelcast map instance matching that definition — e.g. the map was never created because the ticket type is new/custom or the registry was configured with maps for only certain ticket types.

Common situations: Adding a custom ticket type without defining a matching Hazelcast map; runtime catalog changes after registry initialization; creating tickets via an extension (e.g. MFA, webflow custom tickets) whose maps aren't registered; config where map names and ticket catalog prefixes drift apart after version upgrade.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/f4f0c5bcd008de9d. 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:95

        val metadata = ticketCatalog.find(ticket);
        val ticketMap = getTicketMapInstanceByMetadata(metadata);

        if (ticketMap != null) {
            val holder = HazelcastTicketDocument
                .builder()
                .id(encTicket.getId())
                .type(metadata.getImplementationClass().getName())
                .principal(digestIdentifier(getPrincipalIdFrom(ticket)))
                .timeToLive(ttl)
                .ticket(encTicket)
                .prefix(metadata.getPrefix())
                .service(ticket instanceof final ServiceAwareTicket sat && Objects.nonNull(sat.getService()) ? sat.getService().getId() : null)
                .attributes(collectAndDigestTicketAttributes(ticket))
                .build();
            ticketMap.set(encTicket.getId(), holder, ttl, TimeUnit.SECONDS);
            LOGGER.debug("Added ticket [{}] with ttl [{}s]", encTicket.getId(), ttl);
        } else {
            LOGGER.warn("Unable to locate ticket map for ticket metadata [{}]", metadata);
        }
        return ticket;
    }

    @Override
    public Ticket getTicket(final String ticketId, final Predicate<Ticket> predicate) {
        val encTicketId = digestIdentifier(ticketId);
        if (StringUtils.isBlank(encTicketId)) {
            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)) {

View on GitHub (pinned to e7288fc434)