{"record":{"id":"e5d4f5b566c22dc8","repo":"xai-org/x-algorithm","slug":"variable-s-cannot-be-defined-there-is-no-scope","errorCode":null,"errorMessage":"variable %s cannot be defined: there is no scope","messagePattern":"variable (.+?) cannot be defined: there is no scope","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/CompilerContext.java","lineNumber":257,"sourceCode":"\n  CompilerScope addScope() throws SemanticCheckFailure {\n    CompilerScope scope =\n        new CompilerScope(NEXT_CONTEXT_ID.getAndIncrement(), currentScope());\n    scopeList.addFirst(scope);\n    return scope;\n  }\n\n  void removeScope() {\n    scopeList.removeFirst();\n  }\n\n  void defineVariable(\n      String variableName,\n      Type returnType,\n      ASTNode astNode) throws SemanticCheckFailure {\n\n    if (scopeList.size() <= 1) {\n      throw new SemanticCheckFailure(\n          String.format(\"variable %s cannot be defined: there is no scope\", variableName));\n    }\n\n    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);","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/CompilerContext.java#L239-L275","documentation":"defineVariable refuses to bind a variable when the scope stack has only the root scope (size <= 1), because variables must live in a nested scope (function body, lambda, let, etc.). The root scope only holds types and units, not user variables.","triggerScenarios":"Calling defineVariable from toVal/toWith/toDerivedFeatureFunction when compiling at root level without having pushed a child scope, e.g. a val definition placed outside a function/module body in the DSL.","commonSituations":"Placing let/val bindings at the top level of an expression where the grammar technically allows it but semantics forbid it; custom DSL transforms emitting variable definitions at root.","solutions":["Move the variable definition inside a function body, lambda, or with/let construct that creates a nested scope","If writing a custom transform, emit an addScope() before defining variables"],"exampleFix":"// before\nval x = 1  // at root scope\n// after\nfn f() { val x = 1; x }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (SemanticCheckFailure e) { /* message names the variable; move definition into a scoped construct */ }","preventionTips":["Define variables only inside function/lambda/with bodies","Lint DSL sources for root-level val definitions"],"tags":["botmaker","scope","variable-definition"],"backgroundTag":"definition-outside-scope","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}