{"record":{"id":"1168e7743a599467","repo":"apereo/cas","slug":"invalidticketexception","errorCode":null,"errorMessage":"InvalidTicketException","messagePattern":"InvalidTicketException","errorType":"exception","errorClass":"InvalidTicketException","httpStatus":400,"severity":"error","filePath":"support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java","lineNumber":96,"sourceCode":"            MediaType.APPLICATION_FORM_URLENCODED_VALUE,\n            MediaType.APPLICATION_JSON_VALUE,\n            MediaType.TEXT_HTML_VALUE,\n            MediaType.TEXT_PLAIN_VALUE\n        })\n    @Operation(summary = \"Create service ticket\",\n        parameters = {\n            @Parameter(name = \"tgtId\", required = true, in = ParameterIn.PATH, description = \"Ticket-granting ticket id\"),\n            @Parameter(name = \"requestBody\", required = false, description = \"Request body containing credentials\")\n        })\n    public ResponseEntity<String> createServiceTicket(\n        final HttpServletRequest httpServletRequest,\n        @RequestBody(required = false)\n        final MultiValueMap<String, String> requestBody,\n        @PathVariable final String tgtId) {\n        try {\n            val authn = ticketRegistrySupport.getAuthenticationFrom(StringEscapeUtils.escapeHtml4(tgtId));\n            if (authn == null) {\n                throw new InvalidTicketException(tgtId);\n            }\n            val service = Objects.requireNonNull(argumentExtractor.extractService(httpServletRequest),\n                \"Target service/application is unspecified or unrecognized in the request\");\n            if (BooleanUtils.toBoolean(httpServletRequest.getParameter(CasProtocolConstants.PARAMETER_RENEW))) {\n                val credential = credentialFactory.fromRequest(httpServletRequest, requestBody);\n                if (credential == null || credential.isEmpty()) {\n                    throw new BadRestRequestException(\"No credentials are provided or extracted to authenticate the REST request\");\n                }\n                val authenticationResult = authenticationSystemSupport.finalizeAuthenticationTransaction(service, credential);\n                return serviceTicketResourceEntityResponseFactory.build(tgtId, service, Objects.requireNonNull(authenticationResult));\n            }\n            val builder = authenticationSystemSupport.getAuthenticationResultBuilderFactory().newBuilder();\n            val authenticationResult = builder.collect(authn).build(service);\n            return serviceTicketResourceEntityResponseFactory.build(tgtId, service, Objects.requireNonNull(authenticationResult));\n        } catch (final InvalidTicketException e) {\n            return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(tgtId) + \" could not be found or is considered invalid\", HttpStatus.NOT_FOUND);\n        } catch (final AuthenticationException e) {\n            return RestResourceUtils.createResponseEntityForAuthnFailure(e, httpServletRequest, applicationContext);","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/ServiceTicketResource.java#L78-L114","documentation":"CAS REST protocol endpoint throws InvalidTicketException when the supplied TGT id cannot be resolved to an authentication in the ticket registry. The endpoint looks up the TicketGrantingTicket's authentication via ticketRegistrySupport; a null result means the TGT is unknown, expired, or already consumed. It is thrown before any service ticket is created.","triggerScenarios":"POST/GET to /v1/tickets/{tgtId} where tgtId does not exist in the ticket registry, the TGT has expired (default 8h idle timeout), the registry was flushed/restarted (in-memory registry), or the tgtId string is malformed/URL-encoded incorrectly so the lookup misses.","commonSituations":"Client waits too long between TGT creation and service ticket requests; CAS restarted with an in-memory ticket registry invalidating all issued TGTs; client sends TGC cookie value from a different CAS node without replicated registry; user forgets to URL-encode the TGT id (TGT-...-cassuffix containing special chars).","solutions":["Re-acquire a fresh TGT first (POST to /v1/tickets with username/password) and retry with the new tgtId.","Increase ticket expiration policy (cas.ticket.tgt.timeout) or configure a persistent/replicated ticket registry (Redis/JDBC/Hazelcast) for multi-node deployments.","Verify the exact tgtId value is passed unmodified and correctly URL-encoded in the request path.","Check ticketRegistrySupport's underlying registry health and that both CAS nodes point at the same registry."],"exampleFix":"// before\ncurl -X POST 'https://cas/v1/tickets/TGT-1-abc/service?service=https://app'\n// after\ncurl -u casuser:password -X POST 'https://cas/v1/tickets' -d 'username=casuser&password=pass' # get fresh TGT\ncurl -X POST 'https://cas/v1/tickets/TGT-2-newid/service' -d 'service=https://app'","handlingStrategy":"validation","validationCode":"// Before calling the endpoint, confirm the TGT exists (or just re-acquire):\nboolean tgtLikelyValid = tgtId != null && tgtId.startsWith(\"TGT-\")\n    && System.currentTimeMillis() - lastTgtFetch < tgtMaxIdleMillis;\nif (!tgtLikelyValid) { tgtId = fetchNewTicketGrantingTicket(user, pass); }","typeGuard":null,"tryCatchPattern":"try { createServiceTicket(tgtId, service); }\ncatch (InvalidTicketException | RestHttpException e) {\n    String freshTgt = fetchNewTicketGrantingTicket(user, pass);\n    createServiceTicket(freshTgt, service);\n}","preventionTips":["Always re-acquire a TGT upon any invalid-ticket response instead of retrying with the same id.","Use a persistent/replicated ticket registry when running multiple CAS nodes.","Track TGT idle timeout client-side and refresh proactively.","URL-encode the TGT id when placing it in the request path."],"tags":["rest","cas","ticket-registry","expired-ticket"],"backgroundTag":"record-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"}