spring-projects/spring-ai · error · IllegalArgumentException

SSE connection ' ' requires a 'url' property. Example: url…

Error message

SSE connection '<connectionName>' requires a 'url' property. Example: url: http://localhost:3000

What it means

SseHttpClientTransportAutoConfiguration builds SSE transports from the spring.ai.mcp.client.sse.connections map. Each named connection must declare a 'url' property; when the URL is null or blank, the configuration fails fast with this IllegalArgumentException naming the offending connection and showing the expected format.

Solutions

  1. Add the url key to the connection: spring.ai.mcp.client.sse.connections.<name>.url=http://localhost:3000
  2. Check YAML indentation so url sits directly under the correct connection name.
  3. Verify any environment placeholder in the value resolves to a non-empty value at runtime.
  4. Fix key typos — the property must be exactly 'url' (sse-endpoint is optional and defaults to /sse).

Example fix

# before
spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            server1:
              sse-endpoint: /sse

# after
spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            server1:
              url: http://localhost:3000
              sse-endpoint: /sse
Defensive patterns

Strategy: validation

Validate before calling

spring.ai.mcp.client.sse.connections.forEach((name, p) -> {
    if (p.url() == null || p.url().trim().isEmpty()) {
        throw new IllegalArgumentException("SSE connection '" + name + "' requires a 'url' property");
    }
});

Type guard

boolean hasValidUrl(SseParameters p) { return p != null && p.url() != null && !p.url().trim().isEmpty(); }

Try / catch

try {
    context = SpringApplication.run(App.class, args);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("SSE connection")) {
        // add the missing url to the named connection in application.yml
    }
    throw e;
}

Prevention

When it happens

Trigger: Defining an MCP SSE connection under spring.ai.mcp.client.sse.connections.<name> without a url key, or with an empty/whitespace-only url, at application startup.

Common situations: Typo in the property key (e.g. 'uri' or 'server-url' instead of 'url'), YAML indentation placing url under the wrong connection, environment-variable placeholders (URL_REPLACED or ${...}) resolving to empty, or copy-pasted config where url was deleted.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/cf538bb3c718c091. Report an issue: GitHub.

Appendix: source

Thrown at auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/src/main/java/org/springframework/ai/mcp/client/httpclient/autoconfigure/SseHttpClientTransportAutoConfiguration.java:115

	 * @return list of named MCP transports
	 */
	@Bean
	public List<NamedClientMcpTransport> sseHttpClientTransports(McpSseClientConnectionDetails connectionDetails,
			ObjectProvider<JsonMapper> jsonMapperProvider,
			ObjectProvider<McpClientCustomizer<HttpClientSseClientTransport.Builder>> transportCustomizers) {

		JsonMapper jsonMapper = jsonMapperProvider.getIfAvailable(JsonMapper::new);

		List<NamedClientMcpTransport> sseTransports = new ArrayList<>();

		for (Map.Entry<String, SseParameters> serverParameters : connectionDetails.getConnections().entrySet()) {
			String connectionName = serverParameters.getKey();
			SseParameters params = serverParameters.getValue();

			String baseUrl = params.url();
			String sseEndpoint = params.sseEndpoint() != null ? params.sseEndpoint() : "/sse";
			if (baseUrl == null || baseUrl.trim().isEmpty()) {
				throw new IllegalArgumentException("SSE connection '" + connectionName
						+ "' requires a 'url' property. Example: url: http://localhost:3000");
			}

			try {
				var transportBuilder = HttpClientSseClientTransport.builder(baseUrl)
					.sseEndpoint(sseEndpoint)
					.clientBuilder(HttpClient.newBuilder())
					.jsonMapper(new JacksonMcpJsonMapper(jsonMapper));

				for (McpClientCustomizer<HttpClientSseClientTransport.Builder> customizer : transportCustomizers) {
					customizer.customize(connectionName, transportBuilder);
				}

				sseTransports.add(new NamedClientMcpTransport(connectionName, transportBuilder.build()));
			}
			catch (Exception e) {
				throw new IllegalArgumentException("Failed to create SSE transport for connection '" + connectionName
						+ "'. Check URL splitting: url='" + baseUrl + "', sse-endpoint='" + sseEndpoint

View on GitHub (pinned to 98a7beda4f)