{"record":{"id":"7c72eec9a47e319b","repo":"apache/shenyu","slug":"websocket-sync-token-is-not-configured","errorCode":null,"errorMessage":"websocket sync token is not configured","messagePattern":"websocket sync token is not configured","errorType":"exception","errorClass":"ShenyuException","httpStatus":null,"severity":"critical","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketConfigurator.java","lineNumber":101,"sourceCode":"        }\n        return super.checkOrigin(originHeaderValue);\n    }\n\n    @Override\n    public void onStartup(final ServletContext servletContext) {\n        int messageMaxSize = getWebsocketSyncProperties().getMessageMaxSize();\n        if (messageMaxSize > 0) {\n            servletContext.setInitParameter(TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM,\n                    String.valueOf(messageMaxSize));\n            servletContext.setInitParameter(BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM,\n                    String.valueOf(messageMaxSize));\n        }\n    }\n\n    private void checkSyncToken(final HandshakeRequest request) {\n        String configuredToken = getWebsocketSyncProperties().getToken();\n        if (StringUtils.isBlank(configuredToken)) {\n            throw new ShenyuException(\"websocket sync token is not configured\");\n        }\n        String requestToken = getHeader(request.getHeaders(), Constants.X_SHENYU_SYNC_TOKEN);\n        if (StringUtils.isBlank(requestToken) || !isSameToken(configuredToken, requestToken)) {\n            throw new ShenyuException(\"websocket sync token is invalid\");\n        }\n    }\n\n    private WebsocketSyncProperties getWebsocketSyncProperties() {\n        return Optional.ofNullable(websocketSyncProperties)\n                .orElseGet(() -> SpringBeanUtils.getInstance().getBean(WebsocketSyncProperties.class));\n    }\n\n    private boolean isSameToken(final String configuredToken, final String requestToken) {\n        return MessageDigest.isEqual(\n                configuredToken.getBytes(StandardCharsets.UTF_8),\n                requestToken.getBytes(StandardCharsets.UTF_8));\n    }\n","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/websocket/WebsocketConfigurator.java#L83-L119","documentation":"WebsocketConfigurator.modifyHandshake authenticates gateway websocket sync clients by comparing the X-Shenyu-Sync-Token header against the token configured in shenyu.sync.websocket.token on the admin. checkSyncToken throws ShenyuException when the admin has no token configured at all, aborting the handshake. ShenYu requires the token for websocket sync security.","triggerScenarios":"A gateway attempts the websocket sync handshake while admin's `shenyu.sync.websocket.token` property is absent or empty in application.yml.","commonSituations":"Fresh admin deployment with a minimal application.yml missing the token; operator deleted the token thinking it optional; upgraded admin where token became mandatory but old config kept; running admin with default config from an older example file.","solutions":["Set a token in admin's application.yml: shenyu.sync.websocket.token: <secret>.","Set the same token in the gateway config (shenyu.sync.websocket.token / websocket sync token) so the handshake passes the next check.","Restart shenyu-admin after adding the property so WebsocketSyncProperties is repopulated.","If deploying via environment variables, ensure SHENYU_SYNC_WEBSOCKET_TOKEN is actually injected into the admin container."],"exampleFix":"// before (admin application.yml)\nshenyu:\n  sync:\n    websocket:\n      enabled: true\n// after\nshenyu:\n  sync:\n    websocket:\n      enabled: true\n      token: \"mySharedSecret\"","handlingStrategy":"validation","validationCode":"// startup check (admin)\n@PostConstruct\nvoid check() {\n    if (websocketSyncProperties.getToken() == null || websocketSyncProperties.getToken().isBlank())\n        throw new IllegalStateException(\"shenyu.sync.websocket.token must be set\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    modifyHandshake(...); // server side\n} catch (ShenyuException e) {\n    LOG.error(\"websocket handshake rejected: {}\", e.getMessage());\n}","preventionTips":["Always set shenyu.sync.websocket.token in admin and gateway configs","Inject the token via secret/env management rather than deleting it","Add a deployment smoke test that opens the websocket sync connection"],"tags":["websocket","security","token","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}