{"record":{"id":"f4f0c5bcd008de9d","repo":"apereo/cas","slug":"unable-to-locate-ticket-map-for-ticket-metadata","errorCode":null,"errorMessage":"Unable to locate ticket map for ticket metadata [{}]","messagePattern":"Unable to locate ticket map for ticket metadata \\[(.+?)\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-hazelcast-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/HazelcastTicketRegistry.java","lineNumber":95,"sourceCode":"        val metadata = ticketCatalog.find(ticket);\n        val ticketMap = getTicketMapInstanceByMetadata(metadata);\n\n        if (ticketMap != null) {\n            val holder = HazelcastTicketDocument\n                .builder()\n                .id(encTicket.getId())\n                .type(metadata.getImplementationClass().getName())\n                .principal(digestIdentifier(getPrincipalIdFrom(ticket)))\n                .timeToLive(ttl)\n                .ticket(encTicket)\n                .prefix(metadata.getPrefix())\n                .service(ticket instanceof final ServiceAwareTicket sat && Objects.nonNull(sat.getService()) ? sat.getService().getId() : null)\n                .attributes(collectAndDigestTicketAttributes(ticket))\n                .build();\n            ticketMap.set(encTicket.getId(), holder, ttl, TimeUnit.SECONDS);\n            LOGGER.debug(\"Added ticket [{}] with ttl [{}s]\", encTicket.getId(), ttl);\n        } else {\n            LOGGER.warn(\"Unable to locate ticket map for ticket metadata [{}]\", metadata);\n        }\n        return ticket;\n    }\n\n    @Override\n    public Ticket getTicket(final String ticketId, final Predicate<Ticket> predicate) {\n        val encTicketId = digestIdentifier(ticketId);\n        if (StringUtils.isBlank(encTicketId)) {\n            return null;\n        }\n        val metadata = ticketCatalog.find(ticketId);\n        if (metadata != null) {\n            val map = getTicketMapInstanceByMetadata(metadata);\n            if (map != null) {\n                val document = map.get(encTicketId);\n                if (document != null && document.getTicket() != null) {\n                    val result = decodeTicket(document.getTicket());\n                    if (predicate != null && predicate.test(result)) {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-hazelcast-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/HazelcastTicketRegistry.java#L77-L113","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure every ticket type in the TicketDefinition catalog has a corresponding Hazelcast map created during registry initialization.","Check the ticket's metadata (prefix/name) against the configured map names in the Hazelcast ticket registry configuration.","If using a custom ticket, register its definition and map in the catalog (TicketCatalogConfigurer) before use.","Enable debug logging to inspect the metadata values being looked up and compare with initialized maps."],"exampleFix":"// before\n@Bean\npublic TicketCatalogConfigurer customTicketCatalog() {\n    return chain -> chain.register(new TicketDefinition()) /* missing map registration */;\n}\n// after — also register the backing map for the definition\n@Bean\npublic HazelcastTicketRegistryConfigurer hazelcastMaps() {\n    return hz -> hz.getMap(\"customTicketMap\");\n}","handlingStrategy":"validation","validationCode":"// Ensure a map exists for the ticket type before adding\nvar metadata = ticketCatalog.findTicketDefinition(ticket).map(TicketDefinition::getProperties);\nvar mapName = ticketCatalog.findTicketDefinition(ticket)\n    .map(d -> d.getProperties().getStorageName()).orElse(null);\nif (mapName == null || hzInstance.getMap(mapName) == null) {\n    throw new IllegalStateException(\"No Hazelcast map registered for ticket type \" + ticket.getId());\n}","typeGuard":"TicketDefinition def = ticketCatalog.findTicketDefinition(ticketId);\nboolean hasMap = def != null && def.getProperties() != null && def.getProperties().getStorageName() != null;","tryCatchPattern":null,"preventionTips":["Register every custom ticket definition AND its backing Hazelcast map in the same configurer.","After upgrading CAS, diff your TicketCatalog/Hazelcast map configuration against the new defaults.","Treat this warning as a persistence-loss alarm: monitor logs and fail health checks if it appears.","Write an integration test that adds and reads each ticket type in your catalog."],"tags":["hazelcast","tickets","registry","configuration"],"backgroundTag":"resource-not-found","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}