spring-projects/spring-ai · warning

Got error when closing transport

Error message

Got error when closing transport

What it means

WebClientStreamableHttpTransport.createTransportSession() builds a Mono that DELETEs the MCP endpoint when a transport session closes. Errors from that close request are logged at WARN ('Got error when closing transport') and swallowed via onErrorComplete — the close failure does not propagate to the caller.

Source

Thrown at mcp/transport/mcp-spring-webflux/src/main/java/org/springframework/ai/mcp/client/webflux/transport/WebClientStreamableHttpTransport.java:184

			this.handler.set(handler);
			if (this.openConnectionOnStartup) {
				logger.debug("Eagerly opening connection on startup");
				return this.reconnect(null).then();
			}
			return Mono.empty();
		});
	}

	private McpTransportSession<Disposable> createTransportSession() {
		Function<String, Publisher<Void>> onClose = sessionId -> sessionId == null ? Mono.empty()
				: this.webClient.delete()
					.uri(this.endpoint)
					.header(HttpHeaders.MCP_SESSION_ID, sessionId)
					.header(HttpHeaders.PROTOCOL_VERSION, this.latestSupportedProtocolVersion)
					.retrieve()
					.toBodilessEntity()
					.onErrorComplete(e -> {
						logger.warn("Got error when closing transport", e);
						return true;
					})
					.then();
		return new DefaultMcpTransportSession(onClose);
	}

	@Override
	public void setExceptionHandler(Consumer<Throwable> handler) {
		logger.debug("Exception handler registered");
		this.exceptionHandler.set(handler);
	}

	private void handleException(Throwable t) {
		if (logger.isDebugEnabled()) {
			logger.debug("Handling exception for session " + sessionIdOrPlaceholder(this.activeSession.get()), t);
		}
		if (t instanceof McpTransportSessionNotFoundException) {
			McpTransportSession<?> invalidSession = this.activeSession.getAndSet(createTransportSession());

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Treat it as benign if it occurs during application shutdown against an already-dead server — the session is gone either way.
  2. If frequent, verify the MCP server supports DELETE-based session termination per the MCP streamable HTTP spec.
  3. Check connectivity/auth to this.endpoint and that the server honors the Mcp-Session-Id header.
  4. Upgrade spring-ai MCP transport versions if the server returns unexpected status codes on close.
Defensive patterns

Strategy: fallback

Try / catch

// already handled internally via onErrorComplete; on your side: mcpClient.close() inside try/finally and ignore close-time warnings

Prevention

When it happens

Trigger: Any MCP client session over the streamable HTTP (WebFlux) transport being closed/disposed while the server is unreachable, has already terminated the session (404 on unknown session id), or rejects the DELETE (auth failure).

Common situations: MCP server restarted or redeployed, invalidating the session id; network drop during shutdown; server not implementing session termination; closing the client after the server already ended the session.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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