spring-projects/spring-ai · error · IllegalArgumentException
URI must not be null or empty
Error message
URI must not be null or empty
What it means
Builder-state validation error thrown when the @McpResource uri attribute is null or empty when building an AbstractMcpResourceMethodCallback. The URI template is required to match client resource requests and extract URI variables.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/resource/AbstractMcpResourceMethodCallback.java:726
*/
public T mimeType(String mimeType) {
this.mimeType = mimeType;
return (T) this;
}
/**
* Validate the builder state.
* @throws IllegalArgumentException if the builder state is invalid
*/
protected void validate() {
if (this.method == null) {
throw new IllegalArgumentException("Method must not be null");
}
if (this.bean == null) {
throw new IllegalArgumentException("Bean must not be null");
}
if (this.uri == null || this.uri.isEmpty()) {
throw new IllegalArgumentException("URI must not be null or empty");
}
if (this.uriTemplateManagerFactory == null) {
this.uriTemplateManagerFactory = new DefaultMcpUriTemplateManagerFactory();
}
if (this.mimeType == null) {
this.mimeType = "text/plain";
}
if (this.name == null) {
this.name = this.method.getName();
}
}
/**
* Build the callback.
* @return A new callback instance
*/
public abstract R build();View on GitHub (pinned to 98a7beda4f)
Solutions
- Set a non-empty URI template: .uri("docs/{id}") or fill in the @McpResource(uri = ...) value
- Validate the annotation value before passing it to the builder
- Follow URI template syntax with variables in braces if URI variables are used
Example fix
// before
McpSyncResourceMethodCallback.builder().bean(bean).method(m).uri("").build();
// after
McpSyncResourceMethodCallback.builder().bean(bean).method(m).uri("docs/{id}").build(); Defensive patterns
Strategy: validation
Validate before calling
if (uri == null || uri.isEmpty()) throw new IllegalStateException("@McpResource uri must be a non-empty URI template"); Type guard
if (!(uri instanceof String u) || u.isBlank()) { throw new IllegalStateException("Missing or blank resource uri"); } Try / catch
try {
var cb = builder().bean(bean).method(method).uri(uri).build();
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("URI must not be null")) throw new IllegalStateException("Set a non-empty uri template on @McpResource", e);
throw e;
} Prevention
- Never leave the uri attribute of @McpResource empty
- Validate annotation values with a startup test
- Use explicit URI templates with {var} placeholders when URI variables are needed
When it happens
Trigger: Programmatic builder usage omitting .uri(...), or an @McpResource annotation with an empty uri value propagated into the builder.
Common situations: Constructing callbacks manually without the uri; reading the annotation value with reflection and getting an empty string; copy-pasted annotation with blanked-out uri.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Method must have parameters for all URI variables. Expected
- URI variable parameters must be of type String: ${method} in
- Bean must not be null
- Method must have exactly 1 parameter (List<McpSchema.Resourc
- Method must have void or Mono<Void> return type:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/cd0eea16f4b38120.
Report an issue: GitHub.