{"record":{"id":"45da8eebab6ab534","repo":"apereo/cas","slug":"could-not-grant-service-ticket-routing-to","errorCode":null,"errorMessage":"Could not grant service ticket [{}]. Routing to [{}]","messagePattern":"Could not grant service ticket \\[(.+?)\\]\\. Routing to \\[(.+?)\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-actions-core/src/main/java/org/apereo/cas/web/flow/GenerateServiceTicketAction.java","lineNumber":116,"sourceCode":"            val credentials = casWebflowCredentialProvider.extract(context);\n            val builder = authenticationSystemSupport.establishAuthenticationContextFromInitial(authentication,\n                credentials.toArray(Credential.EMPTY_CREDENTIALS_ARRAY));\n            val authenticationResult = builder.build(service);\n\n            LOGGER.trace(\"Built the final authentication result [{}] to grant service ticket to [{}]\", authenticationResult, service);\n            grantServiceTicket(authenticationResult, service, context);\n            return success();\n\n        } catch (final Throwable e) {\n            if (e instanceof InvalidTicketException) {\n                LOGGER.debug(\"CAS has determined ticket-granting ticket [{}] is invalid and must be destroyed\", ticketGrantingTicket);\n                ticketRegistrySupport.getTicketRegistry().deleteTicket(ticketGrantingTicket);\n            }\n            if (isGatewayPresent(context)) {\n                LOGGER.debug(\"Request indicates that it is gateway. Routing result to [{}] state\", CasWebflowConstants.TRANSITION_ID_GATEWAY);\n                return result(CasWebflowConstants.TRANSITION_ID_GATEWAY);\n            }\n            LOGGER.warn(\"Could not grant service ticket [{}]. Routing to [{}]\", e.getMessage(), CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE);\n            return newEvent(CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE, e);\n        }\n    }\n\n    private void grantServiceTicket(final AuthenticationResult authenticationResult,\n                                    final Service service,\n                                    final RequestContext requestContext) {\n        serviceTicketAuthorities\n            .stream()\n            .sorted(AnnotationAwareOrderComparator.INSTANCE)\n            .filter(auth -> auth.supports(authenticationResult, service))\n            .findFirst()\n            .ifPresent(Unchecked.consumer(auth -> {\n                if (auth.shouldGenerate(authenticationResult, service)) {\n                    FunctionUtils.doUnchecked(_ -> {\n                        val ticketGrantingTicket = WebUtils.getTicketGrantingTicketId(requestContext);\n                        val serviceTicketId = centralAuthenticationService.grantServiceTicket(ticketGrantingTicket, service, authenticationResult);\n                        WebUtils.putServiceTicketInRequestScope(requestContext, serviceTicketId);","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-actions-core/src/main/java/org/apereo/cas/web/flow/GenerateServiceTicketAction.java#L98-L134","documentation":"This is a WARN log emitted by the CAS GenerateServiceTicketAction when a service ticket cannot be granted from the presented ticket-granting ticket (TGT). After the failure, the webflow is routed to the 'authenticationFailure' transition, so the login flow terminates with an authentication failure event rather than a service ticket.","triggerScenarios":"doExecuteInternal catches a throwable raised inside grantServiceTicket (e.g. TicketException from ticketRegistry.addTicket, expired/invalid TGT, service not authorized for the TGT) and logs this message before returning the authentication-failure event.","commonSituations":"TGT expired or evicted from the ticket registry (short ticket timeout, shared registry like Redis/JDBC flushed); service ID mismatch between the service presented and the one bound to the TGT; ticket registry connectivity problems; service not found/authorized in the services registry.","solutions":["Check the accompanying exception message (the {} placeholder shows e.getMessage()) to identify the root cause (expired TGT vs registry error).","Verify the ticket registry (cas.ticket.registry.*) is up, shared across CAS nodes, and not dropping tickets prematurely.","Confirm the service parameter matches a registered service in the services registry and that the TGT was issued for the same service context.","Increase ticket-granting-ticket timeout (cas.ticket.tgt.time-to-kill-in-seconds) if tickets expire mid-flow."],"exampleFix":"// before: TGT expires before ST request\ncas.ticket.tgt.time-to-kill-in-seconds=10\n// after\ncas.ticket.tgt.time-to-kill-in-seconds=28800","handlingStrategy":"try-catch","validationCode":"// before triggering the ST grant\nval tgt = ticketRegistrySupport.getTicketRegistry().getTicket(tgtId, TicketGrantingTicket.class);\nif (tgt == null || tgt.isExpired()) { return error(\"expired\"); }\nif (servicesManager.findServiceBy(service) == null) { return error(\"unauthorized-service\"); }","typeGuard":"function isLiveTgt(t: Ticket | null): t is TicketGrantingTicket {\n  return t instanceof TicketGrantingTicket && !t.isExpired();\n}","tryCatchPattern":"try {\n  return grantServiceTicket(authnResult, service, context);\n} catch (TicketException | AbstractTicketException e) {\n  LOGGER.warn(\"Could not grant service ticket: [{}]\", e.getMessage());\n  return newEvent(CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE, e);\n}","preventionTips":["Monitor ticket registry health and eviction metrics across CAS nodes.","Keep TGT time-to-kill comfortably longer than the maximum SSO session length.","Always register services in the services registry before enabling clients to hit /login.","Inspect the exception message embedded in the log ({} placeholder) rather than the warning alone."],"tags":["cas","webflow","service-ticket","ticket-registry"],"backgroundTag":"invalid-state-transition","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"}