spring-projects/spring-ai · error · IllegalStateException

Sampling not supported by the client:

Error message

Sampling not supported by the client: 

What it means

DefaultMcpSyncRequestContext.sample(Consumer<SamplingSpec>) throws IllegalStateException when the connected MCP client has not declared support for sampling. The MCP server can only request LLM completions ('create message') via the client if the client's capabilities include sampling. The client info is appended to the message for diagnostics.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/context/DefaultMcpSyncRequestContext.java:238

	// Sampling

	@Override
	public boolean sampleEnabled() {
		return !(this.exchange.getClientCapabilities() == null
				|| this.exchange.getClientCapabilities().sampling() == null);
	}

	@Override
	public CreateMessageResult sample(String... messages) {
		return this.sample(s -> s.message(messages));
	}

	@Override
	public CreateMessageResult sample(Consumer<SamplingSpec> samplingSpec) {

		if (!this.sampleEnabled()) {
			throw new IllegalStateException("Sampling not supported by the client: " + this.exchange.getClientInfo());
		}

		Assert.notNull(samplingSpec, "Sampling spec consumer must not be null");

		DefaultSamplingSpec spec = new DefaultSamplingSpec();
		samplingSpec.accept(spec);

		var progressToken = this.request.progressToken();

		return this.sample(McpSchema.CreateMessageRequest
			.builder(spec.messages, spec.maxTokens != null && spec.maxTokens > 0 ? spec.maxTokens : 500)
			.modelPreferences(spec.modelPreferences)
			.systemPrompt(spec.systemPrompt)
			.temperature(spec.temperature)
			.stopSequences(spec.stopSequences.isEmpty() ? null : spec.stopSequences)
			.includeContext(spec.includeContextStrategy)
			.meta(spec.metadata.isEmpty() ? null : spec.metadata)
			.progressToken(progressToken)

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Enable sampling on the client side: include sampling capabilities when building the MCP client during client initialization and reconnect
  2. Wrap sample() in a capability check (sampleEnabled()) and provide a fallback (local model call or default response) when sampling is unsupported
  3. Verify the connected client is one that supports sampling; document the requirement or degrade tool behavior when it does not

Example fix

// before
CreateMessageResult result = ctx.sample(spec -> spec.messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER, new McpSchema.TextContent("summarize")))));
// after
CreateMessageResult result = ctx.sampleEnabled()
    ? ctx.sample(spec -> spec.messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER, new McpSchema.TextContent("summarize")))))
    : fallbackSummarize();
Defensive patterns

Strategy: validation

Validate before calling

if (!ctx.sampleEnabled()) { throw new ToolExecutionException("Client does not support sampling: " + clientInfo); }

Type guard

boolean samplingAvailable = ctx.sampleEnabled();

Try / catch

try { return ctx.sample(spec); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Sampling not supported")) { return fallback(); } throw e; }

Prevention

When it happens

Trigger: Calling ctx.sample(specConsumer) from a @McpTool or other annotated handler when the exchange's client capabilities do not include sampling (sampleEnabled() returns false). Typically happens with clients that never enabled sampling in their initialize request.

Common situations: A server tool tries to delegate work to the client's LLM, but the client is a plain MCP host built without sampling enabled (sampling capability not set), or a CLI/test client connects without sampling support. Also occurs after client library upgrades where sampling capability flags reset.

Related errors


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