spring-projects/spring-ai · error · IllegalArgumentException

textContent and resource cannot be set at the same time

Error message

textContent and resource cannot be set at the same time

What it means

UserMessage.Builder.build() enforces mutual exclusivity between textContent and resource: the message text may come either from an inline string or from a Resource, not both. Supplying both throws IllegalArgumentException.

Solutions

  1. Keep only one of text(...) / resource(...) in the builder chain
  2. If the resource is optional fallback, wrap the choice in an if/else so only one is set
  3. Read the resource to a String yourself and pass it via text(...) when you need to combine content programmatically

Example fix

// before
UserMessage msg = UserMessage.builder()
    .text("Summarize this").resource(new ClassPathResource("input.txt")).build();
// after
UserMessage msg = UserMessage.builder()
    .resource(new ClassPathResource("input.txt")).build();
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.hasText(text) && resource != null) {
    throw new IllegalArgumentException("Set either text or resource, not both");
}

Try / catch

try {
    UserMessage msg = builder.build();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("textContent and resource")) { /* rebuild with a single source */ }
    throw e;
}

Prevention

When it happens

Trigger: Calling UserMessage.builder().text("hi").resource(myResource).build(); chaining both text and resource setters before build().

Common situations: Migrating from text-based prompts to resource-based prompts and leaving both setters in the chain; templating code that conditionally adds text but also always sets a default resource.

Related errors


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

Appendix: source

Thrown at spring-ai-model/src/main/java/org/springframework/ai/chat/messages/UserMessage.java:122

		public Builder media(List<Media> media) {
			this.media = media;
			return this;
		}

		public Builder media(Media... media) {
			this.media = Arrays.asList(media);
			return this;
		}

		public Builder metadata(Map<String, Object> metadata) {
			this.metadata = metadata;
			return this;
		}

		public UserMessage build() {
			if (StringUtils.hasText(this.textContent) && this.resource != null) {
				throw new IllegalArgumentException("textContent and resource cannot be set at the same time");
			}
			else if (this.resource != null) {
				this.textContent = MessageUtils.readResource(this.resource);
			}
			return new UserMessage(this.textContent, this.media, this.metadata);
		}

	}

}

View on GitHub (pinned to 98a7beda4f)