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

  1. Add the missing variables (listed in the exception message) to the options Map passed to the renderer/template.
  2. Fix misspellings so option keys exactly match the variable names in the template.
  3. If intentional partial rendering is desired, set the renderer's validationMode to ValidationMode.WARN (or OFF if available) instead of THROW.
  4. 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

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


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