xai-org/x-algorithm · error · SemanticCheckFailure

variable %s not defined

Error message

variable %s not defined

What it means

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.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/compiler/CompilerContext.java:279

    CompilerScope currentScope = scopeList.getFirst();
    Parameter parameter = Parameter.variable(variableName, returnType, astNode);
    currentScope.defineVariable(parameter);
  }

  void defineVariable(
      String variableName,
      ASTNode astNode) throws SemanticCheckFailure {
    defineVariable(variableName, astNode.getReturnType(), astNode);
  }

  Variable getVariable(String variableText) throws SemanticCheckFailure {
    for (CompilerScope scope : scopeList) {
      if (scope.isVariableDefined(variableText)) {
        Parameter parameter = scope.getVariable(variableText);
        return new Variable(variableText, parameter);
      }
    }
    throw new SemanticCheckFailure(String.format("variable %s not defined", variableText));
  }

  TypeContext getTypeContext() throws SemanticCheckFailure {
    if (scopeList.isEmpty()) {
      throw new SemanticCheckFailure("There is no type context");
    }

    return scopeList.getFirst();
  }

  void defineType(ThriftType thriftType, String alias) throws SemanticCheckFailure {
    if (scopeList.size() <= 1) {
      throw new SemanticCheckFailure(
          String.format("type cannot defined in root scope: %s", alias));
    }

    CompilerScope scope = currentScope();
    scope.defineType(thriftType, alias);

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Fix the spelling of the variable to match its binder
  2. Ensure the reference is inside the construct that binds the variable (lambda/forEach/with/val)
  3. Introduce the variable with a binding form before using it

Example fix

// before
filter(x, > 0)  // x unbound
// after
forEach(items, filter(x, x > 0))  // hmm invalid; use binders that exist
Defensive patterns

Strategy: validation

Validate before calling

boolean defined = false;
for (CompilerScope s : scopes) if (s.isVariableDefined(name)) { defined = true; break; }
if (!defined) throw new IllegalArgumentException("undefined variable: " + name);

Try / catch

catch (SemanticCheckFailure e) { if (e.getMessage().startsWith("variable") && e.getMessage().endsWith("not defined")) { /* check binders and spelling */ } }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/d12467ddde2534c3. Report an issue: GitHub.