{"record":{"id":"2f958acf8a142186","repo":"apereo/cas","slug":"ticket-created-second-s-in-the-future-check","errorCode":null,"errorMessage":"Ticket created [{}] second(s) in the future. Check time synchronization on all servers.","messagePattern":"Ticket created \\[(.+?)\\] second\\(s\\) in the future\\. Check time synchronization on all servers\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java","lineNumber":133,"sourceCode":"                if (ticket instanceof final TicketGrantingTicket tgt) {\n                    applicationContext.publishEvent(new CasRequestSingleLogoutEvent(this, tgt, clientInfo));\n                }\n                try {\n                    deleteTicket(ticket);\n                    if (ticket instanceof final TicketGrantingTicket tgt) {\n                        applicationContext.publishEvent(new CasTicketGrantingTicketDestroyedEvent(this, tgt, clientInfo));\n                    }\n                } catch (final Exception e) {\n                    LoggingUtils.warn(LOGGER, e);\n                }\n                return false;\n            }\n            return true;\n        });\n        if (returnTicket != null) {\n            val ticketAgeSeconds = getTicketAgeSeconds(returnTicket);\n            if (ticketAgeSeconds < -1) {\n                LOGGER.warn(\"Ticket created [{}] second(s) in the future. Check time synchronization on all servers.\", ticketAgeSeconds * -1);\n            }\n        }\n        return returnTicket;\n    }\n\n    @Override\n    public <T extends Ticket> T getTicket(final String ticketId, final @NonNull Class<T> clazz) {\n        val ticket = getTicket(ticketId);\n        if (ticket == null) {\n            LOGGER.debug(\"Ticket [{}] with type [{}] cannot be found\", ticketId, clazz.getSimpleName());\n            throw new InvalidTicketException(ticketId);\n        }\n        if (!clazz.isAssignableFrom(ticket.getClass())) {\n            throw new ClassCastException(\"Ticket [\" + ticket.getId() + \" is of type \"\n                + ticket.getClass() + \" when we were expecting \" + clazz);\n        }\n        return clazz.cast(ticket);\n    }","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core-tickets-api/src/main/java/org/apereo/cas/ticket/registry/AbstractTicketRegistry.java#L115-L151","documentation":"AbstractTicketRegistry.getTicket computes the ticket's age from its creation timestamp. If the age is less than -1 seconds, the ticket appears to have been created in the future relative to the current node's clock, so it warns that time is not synchronized across servers. Clock skew between CAS nodes (or clients writing ticket timestamps) can break expiration math and throttled-use policies.","triggerScenarios":"getTicket(id) on a cluster where the node serving the read has a clock behind the node that created the ticket by more than 1 second — ticketAgeSeconds < -1 in getTicket.","commonSituations":"Multi-node CAS deployments without NTP; VM/container clock drift (paused VMs, Docker on hosts with skewed clocks); load balancer routing a validation request to a lagging node right after ticket creation.","solutions":["Enable and verify NTP/chrony time synchronization on all CAS nodes and the container hosts.","Check clock offsets (chronyc tracking / ntpq -p) on the node producing the warning versus siblings.","Ensure containers use the host clock (mount /etc/localtime or use host time sync) and are not drifting.","If skew is unavoidable at the sub-2s level, note the -1 threshold; otherwise treat persistent warnings as a serious cluster-time drift issue because expiration policies depend on wall-clock time."],"exampleFix":"# before: node clocks drifting\n# after\nsudo apt install chrony && sudo systemctl enable --now chrony\nchronyc tracking  # verify offset is <100ms on every CAS node","handlingStrategy":"validation","validationCode":"// deployment check: fail health probe if clock offset exceeds threshold\nOffsetSeconds offset = readNtpOffset();\nif (Math.abs(offset.value) > 1) { throw new IllegalStateException(\"Clock skew \" + offset + \"s exceeds 1s; sync NTP\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run chrony/NTP on every CAS node and container host","Include clock-offset checks in health endpoints or readiness probes","After VM resume or host maintenance, verify clock resync before resuming traffic"],"tags":["cas","clock-skew","distributed-systems","ntp"],"backgroundTag":"clock-skew-detected","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"}