{"record":{"id":"2adfb5173d6f23b9","repo":"spring-projects/spring-ai","slug":"think-level-must-be-one-of","errorCode":null,"errorMessage":"think level must be one of ","messagePattern":"think level must be one of ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/ThinkOption.java","lineNumber":152,"sourceCode":"\t\tpublic static final ThinkLevel LOW = new ThinkLevel(\"low\");\n\n\t\t/**\n\t\t * Medium thinking level for GPT-OSS.\n\t\t */\n\t\tpublic static final ThinkLevel MEDIUM = new ThinkLevel(\"medium\");\n\n\t\t/**\n\t\t * High thinking level for GPT-OSS.\n\t\t */\n\t\tpublic static final ThinkLevel HIGH = new ThinkLevel(\"high\");\n\n\t\t/**\n\t\t * models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/ThinkOption.java\n\t\t * Creates a new ThinkLevel with validation.\n\t\t */\n\t\tpublic ThinkLevel {\n\t\t\tif (level != null && !VALID_LEVELS.contains(level)) {\n\t\t\t\tthrow new IllegalArgumentException(\"think level must be one of \" + VALID_LEVELS + \", got: \" + level);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic Object toJsonValue() {\n\t\t\treturn this.level;\n\t\t}\n\n\t}\n\n}\n","sourceCodeStart":134,"sourceCodeEnd":164,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/ThinkOption.java#L134-L164","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nThinkOption think = new ThinkLevel(config.getThinkLevel()); // \"High\"\n// after\nString lvl = config.getThinkLevel() == null ? null : config.getThinkLevel().trim().toLowerCase(Locale.ROOT);\nThinkOption think = \"high\".equals(lvl) ? ThinkLevel.HIGH : \"medium\".equals(lvl) ? ThinkLevel.MEDIUM : \"low\".equals(lvl) ? ThinkLevel.LOW : null;","handlingStrategy":"validation","validationCode":"void validateThinkLevel(String level) {\n    if (level != null && !List.of(\"low\", \"medium\", \"high\").contains(level.trim().toLowerCase(Locale.ROOT))) {\n        throw new IllegalArgumentException(\"think level must be low, medium or high, got: \" + level);\n    }\n}","typeGuard":"boolean isValidThinkLevel(String s) {\n    return s != null && (s.equals(\"low\") || s.equals(\"medium\") || s.equals(\"high\"));\n}","tryCatchPattern":"try {\n    ThinkLevel level = new ThinkLevel(userValue);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"think level must be one of\")) {\n        level = ThinkLevel.MEDIUM; // documented default\n    } else throw e;\n}","preventionTips":["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."],"tags":["validation","enum","ollama","illegal-argument"],"backgroundTag":"invalid-enum-value","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}