spring-projects/spring-ai · error · IllegalArgumentException
think level must be one of
Error message
think level must be one of
What it means
The ThinkLevel compact record constructor validates its level string against VALID_LEVELS = ["low", "medium", "high"] (case-sensitive). Any other non-null string — including different casing or empty strings — triggers this IllegalArgumentException, because only GPT-OSS-style levels are valid ThinkLevel values.
Source
Thrown at models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/ThinkOption.java:152
public static final ThinkLevel LOW = new ThinkLevel("low");
/**
* Medium thinking level for GPT-OSS.
*/
public static final ThinkLevel MEDIUM = new ThinkLevel("medium");
/**
* High thinking level for GPT-OSS.
*/
public static final ThinkLevel HIGH = new ThinkLevel("high");
/**
* models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/ThinkOption.java
* Creates a new ThinkLevel with validation.
*/
public ThinkLevel {
if (level != null && !VALID_LEVELS.contains(level)) {
throw new IllegalArgumentException("think level must be one of " + VALID_LEVELS + ", got: " + level);
}
}
@Override
public Object toJsonValue() {
return this.level;
}
}
}
View on GitHub (pinned to 98a7beda4f)
Solutions
- Use the provided constants ThinkLevel.LOW, ThinkLevel.MEDIUM, or ThinkLevel.HIGH instead of raw strings.
- If the value is dynamic, call level.trim().toLowerCase(Locale.ROOT) and validate membership in {low, medium, high} before constructing ThinkLevel.
- For enable/disable semantics on Qwen 3/DeepSeek models, use ThinkBoolean.ENABLED/DISABLED instead of ThinkLevel.
- Reject or default invalid config values at application startup with an explicit error message.
Example fix
// before ThinkOption think = new ThinkLevel(config.getThinkLevel()); // "High" // after String lvl = config.getThinkLevel() == null ? null : config.getThinkLevel().trim().toLowerCase(Locale.ROOT); ThinkOption think = "high".equals(lvl) ? ThinkLevel.HIGH : "medium".equals(lvl) ? ThinkLevel.MEDIUM : "low".equals(lvl) ? ThinkLevel.LOW : null;
Defensive patterns
Strategy: validation
Validate before calling
void validateThinkLevel(String level) {
if (level != null && !List.of("low", "medium", "high").contains(level.trim().toLowerCase(Locale.ROOT))) {
throw new IllegalArgumentException("think level must be low, medium or high, got: " + level);
}
} Type guard
boolean isValidThinkLevel(String s) {
return s != null && (s.equals("low") || s.equals("medium") || s.equals("high"));
} Try / catch
try {
ThinkLevel level = new ThinkLevel(userValue);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("think level must be one of")) {
level = ThinkLevel.MEDIUM; // documented default
} else throw e;
} Prevention
- Prefer the constants ThinkLevel.LOW/MEDIUM/HIGH over raw strings.
- Normalize user/config input with trim().toLowerCase(Locale.ROOT) before constructing.
- Use ThinkBoolean.ENABLED/DISABLED for models that only support on/off thinking.
- Validate think-level config values at application startup, not per-request.
When it happens
Trigger: Calling new ThinkLevel("Low"), ThinkLevel(""), ThinkLevel("minimal"), or any string outside {low, medium, high}; also triggered indirectly by the ThinkOption deserializer when a JSON string think value is not one of the three valid levels.
Common situations: Passing a user-supplied or config-driven think level without normalizing case ("High"); porting code that used other level vocabularies (e.g. "none", "auto", "extreme"); typo like "hig" or "meduim"; binding external JSON with an unexpected level string.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- No embedding input is provided - instructions list is empty
- No embedding input is provided - all texts are null or empty
- ImagePrompt must contain at least one non-empty message
- model cannot be null or empty
- Unsupported message type:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/2adfb5173d6f23b9.
Report an issue: GitHub.