spring-projects/spring-ai · error · IllegalStateException
Not all variables were replaced in the template. Missing var
Error message
Not all variables were replaced in the template. Missing variable names are: %s.
What it means
StTemplateRenderer.validate() checks that every variable referenced by the StringTemplate (ST) template is supplied in the options map. When variables are still missing after validation, and the renderer's validationMode is ValidationMode.THROW, it throws this IllegalStateException naming the missing variables. This guards against silently rendering a template with unfilled placeholders.
Source
Thrown at spring-ai-template-st/src/main/java/org/springframework/ai/template/st/StTemplateRenderer.java:145
/**
* Validates that all required template variables are provided in the model. Returns
* the set of missing variables for further handling or logging.
* @param st the StringTemplate instance
* @param templateVariables the provided variables
* @return set of missing variable names, or empty set if none are missing
*/
private Set<String> validate(ST st, Map<String, ? extends @Nullable Object> templateVariables) {
Set<String> templateTokens = getInputVariables(st);
Set<String> modelKeys = templateVariables.keySet();
Set<String> missingVariables = new HashSet<>(templateTokens);
missingVariables.removeAll(modelKeys);
if (!missingVariables.isEmpty()) {
if (this.validationMode == ValidationMode.WARN) {
logger.warn(VALIDATION_MESSAGE.formatted(missingVariables));
}
else if (this.validationMode == ValidationMode.THROW) {
throw new IllegalStateException(VALIDATION_MESSAGE.formatted(missingVariables));
}
}
return missingVariables;
}
private Set<String> getInputVariables(ST st) {
TokenStream tokens = st.impl.tokens;
Set<String> inputVariables = new HashSet<>();
boolean isInsideList = false;
for (int i = 0; i < tokens.size(); i++) {
Token token = tokens.get(i);
// Handle list variables with option (e.g., {items; separator=", "})
if (token.getType() == STLexer.LDELIM && i + 1 < tokens.size()
&& tokens.get(i + 1).getType() == STLexer.ID) {
if (i + 2 < tokens.size() && tokens.get(i + 2).getType() == STLexer.COLON) {
String text = tokens.get(i + 1).getText();View on GitHub (pinned to 98a7beda4f)
Solutions
- Add the missing variables (listed in the exception message) to the options Map passed to the renderer/template.
- Fix misspellings so option keys exactly match the variable names in the template.
- If intentional partial rendering is desired, set the renderer's validationMode to ValidationMode.WARN (or OFF if available) instead of THROW.
- Prefer validationMode.THROW in production and pre-render template variable extraction (getInputVariables) to align options with template variables.
Example fix
// before
Map.of("topic", "ai") with template "Explain {topic} to {audience}"
// throws IllegalStateException
// after
Map.of("topic", "ai", "audience", "developers") Defensive patterns
Strategy: validation
Validate before calling
// Java: validate before rendering
Set<String> inputVars = templateRenderer.getInputVariables(templateString); // or extract via ST
Set<String> provided = options.keySet();
Set<String> missing = new HashSet<>(inputVars); missing.removeAll(provided);
if (!missing.isEmpty()) throw new IllegalArgumentException("Missing template variables: " + missing); Try / catch
// catch IllegalStateException from create/apply
try {
Prompt prompt = templateRenderer.create(new PromptTemplateOptions(template, options));
} catch (IllegalStateException e) {
logger.warn("Template validation failed: {}", e.getMessage());
// fall back to a default template or surface a 400 to the caller
} Prevention
- Keep option keys and template placeholders derived from a single constant source.
- Use getTemplateFormat/getInputVariables to diff template variables against options in tests.
- Set ValidationMode.THROW in CI to catch template/option mismatches early.
When it happens
Trigger: Calling StTemplateRenderer.create(...) or apply() with a template that references variables (e.g. {prompt}) but passing an options map lacking those keys; also triggered when variable names are misspelled or when ST4 reserved syntax requires variables the caller did not provide.
Common situations: Developers switching prompt templates between renderers: STOP-based templates use {var} while ST4 templates need {var;options}, or prompts copied from examples that reference variables like {documents} never populated in the PromptTemplate options; typos between placeholder names and options keys.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- SSE connection '<connectionName>' requires a 'url' property.
- Sampling not supported by the client:
- Method must not be null
- Method must have exactly 1 parameter (List<McpSchema.Prompt>
- Method must have exactly 1 parameter (List<McpSchema.Resourc
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/fc6d9a495986bf0f.
Report an issue: GitHub.