spring-projects/spring-ai · error · IllegalArgumentException

ThinkingLevel.%s is not supported for model '%s'. Supported

Error message

ThinkingLevel.%s is not supported for model '%s'. Supported levels: %s.

What it means

Model-capability guard in GoogleGenAiChatModel.validateThinkingLevelForModel: the requested GoogleGenAiThinkingLevel is not in the per-model supported set looked up by model id (Vertex-style resource names are reduced to the last path segment), so the request would fail or be ignored by that model.

Source

Thrown at models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/GoogleGenAiChatModel.java:930

	private static void validateThinkingLevelForModel(GoogleGenAiThinkingLevel level, String modelName) {
		if (level == null || level == GoogleGenAiThinkingLevel.THINKING_LEVEL_UNSPECIFIED || modelName == null) {
			return;
		}
		// Vertex AI style full resource names (e.g.
		// "projects/{project}/locations/{location}/publishers/google/models/{model}")
		// carry the model id as the last path segment.
		String modelId = modelName.substring(modelName.lastIndexOf('/') + 1).toLowerCase(Locale.ROOT);
		Set<GoogleGenAiThinkingLevel> supportedLevels = THINKING_LEVEL_SUPPORT_BY_MODEL.get(modelId);
		if (supportedLevels == null) {
			return;
		}
		if (!supportedLevels.contains(level)) {
			if (supportedLevels.isEmpty()) {
				throw new IllegalArgumentException(String.format(
						"ThinkingLevel.%s is not supported for model '%s'. This model does not support thinkingLevel; use thinkingBudget instead.",
						level, modelName));
			}
			throw new IllegalArgumentException(
					String.format("ThinkingLevel.%s is not supported for model '%s'. Supported levels: %s.", level,
							modelName, supportedLevels.stream().map(Enum::name).collect(Collectors.joining(", "))));
		}
	}

	private List<Content> toGeminiContent(List<Message> instructions) {

		List<Content> contents = instructions.stream()
			.map(message -> Content.builder()
				.role(toGeminiMessageType(message.getMessageType()).getValue())
				.parts(messageToGeminiParts(message))
				.build())
			.toList();

		return contents;
	}

	private List<SafetySetting> toGeminiSafetySettings(List<GoogleGenAiSafetySetting> safetySettings) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Use a model that supports the requested thinking level
  2. Omit thinkingLevel or use THINKING_LEVEL_UNSPECIFIED
  3. Pick a level from the supported-levels list in the message

Example fix

// before
options.thinkingLevel(GoogleGenAiThinkingLevel.THINKING_LEVEL_HIGH) // on a LOW/MEDIUM-only model
// after
options.thinkingLevel(GoogleGenAiThinkingLevel.THINKING_LEVEL_MEDIUM)
Defensive patterns

Strategy: validation

Validate before calling

// validate against the level list reported by the error/docs
if (!Set.of(THINKING_LEVEL_LOW, THINKING_LEVEL_MEDIUM).contains(level)) {
    throw new IllegalArgumentException("level not supported for this model");
}

Try / catch

try { model.call(prompt); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Supported levels:")) pickSupportedLevel(e.getMessage()); else throw e; }

Prevention

When it happens

Trigger: Requesting a ThinkingLevel (e.g. THINKING_LEVEL_HIGH) on a model whose THINKING_LEVEL_SUPPORT_BY_MODEL entry contains other levels only (e.g. a model supporting only THINKING_LEVEL_LOW and THINKING_LEVEL_MEDIUM).

Common situations: Sharing options templates across Gemini 2.5 variants with differing level support; hardcoding a level tuned for Pro on Flash models; after changing model IDs in configuration.

Related errors


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