spring-projects/spring-ai · warning

No sampling methods found

Error message

No sampling methods found

What it means

AsyncMcpSamplingProvider.getSamplingSpecifictions logs 'No sampling methods found' when scanning the configured objects for @McpSampling-annotated methods yields an empty handler list. The provider returns nothing, so the MCP server registers no sampling handlers. This warns that sampling support is effectively disabled despite the provider being wired.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/sampling/AsyncMcpSamplingProvider.java:112

				.sorted((m1, m2) -> m1.getName().compareTo(m2.getName()))
				.map(mcpSamplingMethod -> {
					var samplingAnnotation = mcpSamplingMethod.getAnnotation(McpSampling.class);

					Function<CreateMessageRequest, Mono<CreateMessageResult>> methodCallback = AsyncMcpSamplingMethodCallback
						.builder()
						.method(mcpSamplingMethod)
						.bean(samplingObject)
						.sampling(samplingAnnotation)
						.build();

					return new AsyncSamplingSpecification(samplingAnnotation.clients(), methodCallback);
				})
				.toList())
			.flatMap(List::stream)
			.toList();

		if (samplingHandlers.isEmpty()) {
			logger.warn("No sampling methods found");
		}
		if (samplingHandlers.size() > 1) {
			if (logger.isWarnEnabled()) {
				logger.warn("Multiple sampling methods found: " + samplingHandlers.size());
			}
		}

		return samplingHandlers;
	}

	/**
	 * Returns the methods of the given bean class.
	 * @param bean the bean instance
	 * @return the methods of the bean class
	 */
	protected Method[] doGetClassMethods(Object bean) {
		return bean.getClass().getDeclaredMethods();
	}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Add a public method annotated with @McpSampling in the object(s) passed to AsyncMcpSamplingProvider.
  2. Verify the sampling handler instances are actually supplied to the provider constructor/builder.
  3. Check method visibility and parameter/return types match what the scanner supports for async sampling.
  4. If sampling is not needed, remove the sampling provider instead of registering an empty one.

Example fix

// before
class Sampler { public String complete(String prompt) { ... } } // no @McpSampling
// after
class Sampler { @McpSampling public CompletableFuture<String> complete(McpSamplingRequest req) { ... } }
Defensive patterns

Strategy: validation

Validate before calling

// Confirm a sampling handler exists before wiring the async provider:
long sampling = Arrays.stream(samplingObject.getClass().getDeclaredMethods())
    .filter(m -> m.isAnnotationPresent(McpSampling.class) && Modifier.isPublic(m.getModifiers()))
    .count();
if (sampling == 0) throw new IllegalStateException(samplingObject + " has no public @McpSampling methods");

Prevention

When it happens

Trigger: Constructing AsyncMcpSamplingProvider with objects lacking any public @McpSampling method, annotated methods filtered out (visibility/signature mismatch), or an empty objects list — empty samplingHandlers triggers the warn at AsyncMcpSamplingProvider.java:112.

Common situations: Sampling handler class never registered with the provider; @McpSampling annotation missing after refactor; method made private; wrong provider type (async provider given sync-style handlers).

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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