{"record":{"id":"d5406e2b56f987fc","repo":"alibaba/spring-ai-alibaba","slug":"not-all-variables-were-replaced-in-the-template-m","errorCode":null,"errorMessage":"Not all variables were replaced in the template. Missing variable names are: %s.","messagePattern":"Not all variables were replaced in the template\\. Missing variable names are: (.+?)\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/renderer/SaaStTemplateRenderer.java","lineNumber":462,"sourceCode":"\t/**\n\t * Validates that all required template variables are provided in the model. Returns\n\t * the set of missing variables for further handling or logging.\n\t * @param st the StringTemplate instance\n\t * @param templateVariables the provided variables\n\t * @return set of missing variable names, or empty set if none are missing\n\t */\n\tprivate Set<String> validate(ST st, Map<String, Object> templateVariables) {\n\t\tSet<String> templateTokens = getInputVariables(st);\n\t\tSet<String> modelKeys = templateVariables.keySet();\n\t\tSet<String> missingVariables = new HashSet<>(templateTokens);\n\t\tmissingVariables.removeAll(modelKeys);\n\n\t\tif (!missingVariables.isEmpty()) {\n\t\t\tif (this.validationMode == ValidationMode.WARN) {\n\t\t\t\tlogger.warn(VALIDATION_MESSAGE.formatted(missingVariables));\n\t\t\t}\n\t\t\telse if (this.validationMode == ValidationMode.THROW) {\n\t\t\t\tthrow new IllegalStateException(VALIDATION_MESSAGE.formatted(missingVariables));\n\t\t\t}\n\t\t}\n\t\treturn missingVariables;\n\t}\n\n\tprivate Set<String> getInputVariables(ST st) {\n\t\tTokenStream tokens = st.impl.tokens;\n\t\tSet<String> inputVariables = new HashSet<>();\n\t\tboolean isInsideList = false;\n\n\t\tfor (int i = 0; i < tokens.size(); i++) {\n\t\t\tToken token = tokens.get(i);\n\n\t\t\t// Handle list variables with option (e.g., {items; separator=\", \"})\n\t\t\tif (token.getType() == STLexer.LDELIM && i + 1 < tokens.size()\n\t\t\t\t\t&& tokens.get(i + 1).getType() == STLexer.ID) {\n\t\t\t\tif (i + 2 < tokens.size() && tokens.get(i + 2).getType() == STLexer.COLON) {\n\t\t\t\t\tString text = tokens.get(i + 1).getText();","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/renderer/SaaStTemplateRenderer.java#L444-L480","documentation":"SaaStTemplateRenderer.validate() compares template variables against the supplied inputs; when variables remain unbound and validationMode is THROW, it throws IllegalStateException listing the missing names. (In WARN mode it only logs.) This guards against silently rendering prompts with unfilled placeholders.","triggerScenarios":"Applying a template whose placeholders (e.g. $tools$, $query$) have no matching keys in the variables map, with ValidationMode.THROW configured.","commonSituations":"Renaming a prompt placeholder without updating the caller's variable map; supplying variables under different key casing/names; conditional placeholders that are only sometimes filled; prompt template updated independently of code.","solutions":["Supply values for every listed missing variable name (the message names them exactly)","Switch the renderer to ValidationMode.WARN or IGNORE if unfilled placeholders are acceptable","Align the prompt template and the code that fills it — remove unused placeholders or add the keys","Default the variables map so optional placeholders always have a value"],"exampleFix":"// before\nMap.of(\"query\", userQuery); // template also needs $tools$\n// after\nMap.of(\"query\", userQuery, \"tools\", toolDescriptions);","handlingStrategy":"try-catch","validationCode":"Set<String> missing = renderer.validate(template, vars); if (!missing.isEmpty()) throw new IllegalStateException(\"Missing template variables: \" + missing);","typeGuard":null,"tryCatchPattern":"try { prompt = renderer.apply(template, vars); } catch (IllegalStateException e) { log.error(\"Unfilled template variables: {}\", e.getMessage()); vars = fillDefaults(vars); prompt = renderer.apply(template, vars); }","preventionTips":["Read the error message — it lists the exact missing variable names","Keep the prompt template and its filling code in sync (review them together)","Use ValidationMode.WARN during development to spot drift early","Provide defaults for optional placeholders in the variables map"],"tags":["java","template","validation","prompt"],"backgroundTag":"missing-required-argument","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}