{"record":{"id":"b26af9410100bb42","repo":"spring-projects/spring-ai","slug":"messageendpoint-must-be-set","errorCode":null,"errorMessage":"MessageEndpoint must be set","messagePattern":"MessageEndpoint must be set","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"mcp/transport/mcp-spring-webmvc/src/main/java/org/springframework/ai/mcp/server/webmvc/transport/WebMvcSseServerTransportProvider.java","lineNumber":676,"sourceCode":"\t\t * @param securityValidator The security validator to use. Must not be null.\n\t\t * @return this builder instance\n\t\t * @throws IllegalArgumentException if securityValidator is null\n\t\t */\n\t\tpublic Builder securityValidator(ServerTransportSecurityValidator securityValidator) {\n\t\t\tAssert.notNull(securityValidator, \"Security validator must not be null\");\n\t\t\tthis.securityValidator = securityValidator;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Builds a new instance of WebMvcSseServerTransportProvider with the configured\n\t\t * settings.\n\t\t * @return A new WebMvcSseServerTransportProvider instance\n\t\t * @throws IllegalStateException if jsonMapper or messageEndpoint is not set\n\t\t */\n\t\tpublic WebMvcSseServerTransportProvider build() {\n\t\t\tif (this.messageEndpoint == null) {\n\t\t\t\tthrow new IllegalStateException(\"MessageEndpoint must be set\");\n\t\t\t}\n\t\t\treturn new WebMvcSseServerTransportProvider(\n\t\t\t\t\tthis.jsonMapper == null ? McpJsonDefaults.getMapper() : this.jsonMapper, this.baseUrl,\n\t\t\t\t\tthis.messageEndpoint, this.sseEndpoint, this.keepAliveInterval, this.contextExtractor,\n\t\t\t\t\tthis.securityValidator);\n\t\t}\n\n\t}\n\n}\n","sourceCodeStart":658,"sourceCodeEnd":687,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/transport/mcp-spring-webmvc/src/main/java/org/springframework/ai/mcp/server/webmvc/transport/WebMvcSseServerTransportProvider.java#L658-L687","documentation":"WebMvcSseServerTransportProvider.Builder.build() validates required builder fields before instantiating the provider. messageEndpoint (the servlet path where clients POST JSON-RPC messages) is mandatory; if it was never set the builder throws IllegalStateException(\"MessageEndpoint must be set\"). The javadoc also notes jsonMapper must be set (otherwise a default mapper is used).","triggerScenarios":"Calling WebMvcSseServerTransportProvider.builder()...build() without invoking .messageEndpoint(String), then deploying/starting the SSE server transport.","commonSituations":"Copy-pasting a builder chain and omitting the messageEndpoint step; conditional configuration that skips the endpoint assignment; confusing baseUrl with messageEndpoint and setting only one.","solutions":["Add .messageEndpoint(\"/message\") (or your chosen POST endpoint path) to the builder chain before build().","Also set baseUrl and sseEndpoint as needed so clients get correct SSE and POST URLs.","If a default is acceptable, wrap the builder in a helper that applies standard endpoint values when unset."],"exampleFix":"// before\nWebMvcSseServerTransportProvider provider = WebMvcSseServerTransportProvider.builder()\n    .sseEndpoint(\"/sse\")\n    .build(); // throws\n\n// after\nWebMvcSseServerTransportProvider provider = WebMvcSseServerTransportProvider.builder()\n    .sseEndpoint(\"/sse\")\n    .messageEndpoint(\"/message\")\n    .build();","handlingStrategy":"validation","validationCode":"// Before building the provider\nObjects.requireNonNull(baseUrl, \"baseUrl must be set\");\nObjects.requireNonNull(messageEndpoint, \"messageEndpoint must be set\");\nObjects.requireNonNull(sseEndpoint, \"sseEndpoint must be set\");","typeGuard":null,"tryCatchPattern":"try {\n    provider = builder.build();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"MessageEndpoint must be set\")) {\n        builder.messageEndpoint(\"/message\");\n        provider = builder.build();\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always call .messageEndpoint(...) in the builder chain — never omit it.","Build transports through a shared factory method that sets all required fields.","Write an integration test that constructs the provider at startup to fail fast on missing builder fields."],"tags":["configuration","mcp","builder","missing-required-argument","webmvc","sse"],"backgroundTag":"missing-required-argument","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}