spring-projects/spring-ai · error · IllegalArgumentException

Only one of prompt or uri can be provided!

Error message

Only one of prompt or uri can be provided!

What it means

AbstractMcpCompleteMethodCallback enforces mutual exclusivity: a completion callback may target a prompt OR a resource URI, but never both. Providing both non-empty values throws this IllegalArgumentException at construction, since the library could not determine which completion target the method serves.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java:90

	 * @param method The method to create a callback for
	 * @param bean The bean instance that contains the method
	 * @param prompt The prompt reference
	 * @param uri The URI reference
	 * @param uriTemplateManagerFactory The URI template manager factory
	 */
	protected AbstractMcpCompleteMethodCallback(Method method, Object bean, String prompt, String uri,
			McpUriTemplateManagerFactory uriTemplateManagerFactory) {

		Assert.notNull(method, "Method can't be null!");
		Assert.notNull(bean, "Bean can't be null!");
		Assert.notNull(uriTemplateManagerFactory, "URI template manager factory can't be null!");

		// Either prompt or uri must be provided, but not both
		if ((prompt == null || prompt.isEmpty()) && (uri == null || uri.isEmpty())) {
			throw new IllegalArgumentException("Either prompt or uri must be provided!");
		}
		if ((prompt != null && !prompt.isEmpty()) && (uri != null && !uri.isEmpty())) {
			throw new IllegalArgumentException("Only one of prompt or uri can be provided!");
		}

		this.method = method;
		this.bean = bean;
		this.prompt = prompt;
		this.uri = uri;

		// Create the CompleteReference based on prompt or uri
		if (prompt != null && !prompt.isEmpty()) {
			this.completeReference = McpSchema.PromptReference.builder(prompt).build();
		}
		else {
			this.completeReference = new McpSchema.ResourceReference(uri);
		}

		if (uri != null && !uri.isEmpty()) {
			this.uriTemplateManager = uriTemplateManagerFactory.create(this.uri);
			this.uriVariables = this.uriTemplateManager.getVariableNames();

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Remove either the prompt or the uri value so exactly one remains.
  2. If you need completions for both a prompt and a resource, register two separate callback methods/specifications.
  3. Audit the @McpComplete annotation attributes to ensure only one target is declared.

Example fix

// before
@McpComplete(prompt = "myPrompt", uri = "file:///{path}") // throws
// after
@McpComplete(prompt = "myPrompt")
Defensive patterns

Strategy: validation

Validate before calling

boolean hasPrompt = prompt != null && !prompt.isEmpty();
boolean hasUri = uri != null && !uri.isEmpty();
if (hasPrompt && hasUri) throw new IllegalStateException("choose either prompt or uri, not both");

Prevention

When it happens

Trigger: Constructing the callback (or annotating with @McpComplete) with both prompt and uri set to non-empty values simultaneously.

Common situations: Copy-pasting a builder/annotation configuration and forgetting to clear the other attribute; combining a prompt-completion example with a resource-completion example; templating code that fills both placeholders.

Related errors


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