{"record":{"id":"d12467ddde2534c3","repo":"xai-org/x-algorithm","slug":"variable-s-not-defined","errorCode":null,"errorMessage":"variable %s not defined","messagePattern":"variable (.+?) not defined","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/CompilerContext.java","lineNumber":279,"sourceCode":"    CompilerScope currentScope = scopeList.getFirst();\n    Parameter parameter = Parameter.variable(variableName, returnType, astNode);\n    currentScope.defineVariable(parameter);\n  }\n\n  void defineVariable(\n      String variableName,\n      ASTNode astNode) throws SemanticCheckFailure {\n    defineVariable(variableName, astNode.getReturnType(), astNode);\n  }\n\n  Variable getVariable(String variableText) throws SemanticCheckFailure {\n    for (CompilerScope scope : scopeList) {\n      if (scope.isVariableDefined(variableText)) {\n        Parameter parameter = scope.getVariable(variableText);\n        return new Variable(variableText, parameter);\n      }\n    }\n    throw new SemanticCheckFailure(String.format(\"variable %s not defined\", variableText));\n  }\n\n  TypeContext getTypeContext() throws SemanticCheckFailure {\n    if (scopeList.isEmpty()) {\n      throw new SemanticCheckFailure(\"There is no type context\");\n    }\n\n    return scopeList.getFirst();\n  }\n\n  void defineType(ThriftType thriftType, String alias) throws SemanticCheckFailure {\n    if (scopeList.size() <= 1) {\n      throw new SemanticCheckFailure(\n          String.format(\"type cannot defined in root scope: %s\", alias));\n    }\n\n    CompilerScope scope = currentScope();\n    scope.defineType(thriftType, alias);","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/CompilerContext.java#L261-L297","documentation":"getVariable walks the scope chain looking for a binding of the given name and throws if no scope defines it. This is the classic 'unresolved identifier' error of the BotMaker DSL compiler.","triggerScenarios":"Referencing a variable in an expression that was never introduced by a parameter, lambda binder, val/with binding, or forEach/fold binder — e.g. using 'x' without 'forEach(x, ...)' wrapping it, or a typo in a variable name.","commonSituations":"Typos in variable names; referencing lambda parameters outside the lambda body; copy-pasting expression fragments that depend on binders defined elsewhere; shadowing/renaming binders during refactors.","solutions":["Fix the spelling of the variable to match its binder","Ensure the reference is inside the construct that binds the variable (lambda/forEach/with/val)","Introduce the variable with a binding form before using it"],"exampleFix":"// before\nfilter(x, > 0)  // x unbound\n// after\nforEach(items, filter(x, x > 0))  // hmm invalid; use binders that exist","handlingStrategy":"validation","validationCode":"boolean defined = false;\nfor (CompilerScope s : scopes) if (s.isVariableDefined(name)) { defined = true; break; }\nif (!defined) throw new IllegalArgumentException(\"undefined variable: \" + name);","typeGuard":null,"tryCatchPattern":"catch (SemanticCheckFailure e) { if (e.getMessage().startsWith(\"variable\") && e.getMessage().endsWith(\"not defined\")) { /* check binders and spelling */ } }","preventionTips":["Ensure references sit inside the binder's scope (forEach/lambda/with)","Use distinct, descriptive binder names to avoid typos"],"tags":["botmaker","name-resolution","variable","semantic-check"],"backgroundTag":"undefined-variable-reference","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}