{"record":{"id":"711194f88d2d65d1","repo":"apereo/cas","slug":"webflow-execution-key-is-invalid","errorCode":null,"errorMessage":"Webflow execution key is invalid","messagePattern":"Webflow execution key is invalid","errorType":"exception","errorClass":"ClientFlowExecutionRepositoryException","httpStatus":null,"severity":"error","filePath":"core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/executor/ClientFlowExecutionRepository.java","lineNumber":156,"sourceCode":"        execution.getConversationScope().put(WEBFLOW_CLIENT_IP_ADDRESS, clientInfo.getClientIpAddress());\n    }\n\n    protected void verifyWebflowSessionIsCorrectlyPinned(final SerializedFlowExecutionState state) {\n        val currentClientInfo = ClientInfoHolder.getClientInfo();\n\n        val conversationScope = state.getConversationScope();\n        val userAgent = (String) conversationScope.get(WEBFLOW_USER_AGENT);\n        val clientIpAddress = (String) conversationScope.get(WEBFLOW_CLIENT_IP_ADDRESS);\n        Assert.hasText(userAgent, \"User-agent cannot be null or empty\");\n        Assert.hasText(clientIpAddress, \"Client IP address cannot be null or empty\");\n\n        if (!Strings.CI.equals(currentClientInfo.getUserAgent(), userAgent)\n            || !Strings.CI.equals(currentClientInfo.getClientIpAddress(), clientIpAddress)) {\n            LOGGER.error(\"User-agent attached to the webflow [{}] does not match the current user-agent [{}] or \"\n                    + \"client IP address attached to the webflow [{}] does not match the current client IP address [{}]. \"\n                    + \"The flow execution key is invalid or likely tampered with.\",\n                userAgent, currentClientInfo.getUserAgent(), clientIpAddress, currentClientInfo.getClientIpAddress());\n            throw new ClientFlowExecutionRepositoryException(\"Webflow execution key is invalid\");\n        }\n    }\n\n\n    @Getter\n    public static class SerializedFlowExecutionState implements Serializable {\n        @Serial\n        private static final long serialVersionUID = -4020991769174829876L;\n\n        private final String flowId;\n\n        private final MutableAttributeMap conversationScope;\n\n        private final FlowExecution execution;\n\n        SerializedFlowExecutionState(final FlowExecution execution) {\n            this.execution = execution;\n            this.flowId = execution.getDefinition().getId();","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/executor/ClientFlowExecutionRepository.java#L138-L174","documentation":"Webflow session pinning is enabled and the restored flow execution's stored user-agent or client IP does not match the current request's, or those values were blank. The execution key is treated as invalid or tampered and ClientFlowExecutionRepositoryException is thrown. The input at fault is the flow execution key (its pinned session attributes vs. current client info).","triggerScenarios":"Thrown at core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/executor/ClientFlowExecutionRepository.java:156 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Restart the flow with a fresh execution key","Check for clients whose user-agent or IP legitimately changes mid-flow (proxies, mobile handoff)","Disable webflow session pinning (cas.webflow.session.pinToSession=false) if not required","Investigate the logged mismatch to rule out actual key tampering/replay"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}