{"record":{"id":"638f915c62752e38","repo":"BoundaryML/baml","slug":"assign-to-undeclared-variable","errorCode":null,"errorMessage":"assign to undeclared variable `{}`","messagePattern":"assign to undeclared variable `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-compiler/src/thir/interpret.rs","lineNumber":1447,"sourceCode":"\nfn declare_with_cell(\n    scopes: &mut [Scope],\n    name: &str,\n    cell: Arc<Mutex<BamlValueWithMeta<ExprMetadata>>>,\n) {\n    if let Some(scope) = scopes.last_mut() {\n        scope.variables.insert(name.to_string(), cell);\n    }\n}\n\nfn assign(scopes: &mut [Scope], name: &str, value: BamlValueWithMeta<ExprMetadata>) -> Result<()> {\n    for s in scopes.iter_mut().rev() {\n        if let Some(cell) = s.variables.get_mut(name) {\n            *cell.lock().unwrap() = value;\n            return Ok(());\n        }\n    }\n    bail!(\"assign to undeclared variable `{}`\", name)\n}\n\nasync fn assign_to_expr<F, Fut>(\n    target: &Expr<ExprMetadata>,\n    new_value: BamlValueWithMeta<ExprMetadata>,\n    scopes: &mut Vec<Scope>,\n    thir: &THir<ExprMetadata>,\n    run_llm_function: &mut F,\n    watch_handler: &SharedWatchHandler,\n    function_name: &str,\n) -> Result<()>\nwhere\n    F: LlmHandler<Fut>,\n    Fut: LlmFuture,\n{\n    let mut current_expr = target;\n    let mut value_to_assign = new_value;\n","sourceCodeStart":1429,"sourceCodeEnd":1465,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-compiler/src/thir/interpret.rs#L1429-L1465","documentation":"The BAML interpreter's `assign` helper walks the active scopes and, when no scope contains a cell for the variable name, bails with `assign to undeclared variable \\`{name}\\``. BAML requires variables to be declared (e.g. via `let` / parameter bindings) before they can be reassigned, so assignment to a never-declared name is a hard runtime error in the interpreted THIR evaluator.","triggerScenarios":"Executing a `x = value` assignment (via `assign_to_expr` on a plain `Expr::Var` target) where `x` was never introduced by a declaration, function parameter, or for-loop binding in any active scope.","commonSituations":"Typo in a variable name on the left side of an assignment (e.g. `mesage = ...` after `let message = ...`); attempting to create a variable by plain assignment in a BAML expression block as if it were Python/JS; using a variable defined in an inner scope after it closed.","solutions":["Declare the variable before assigning to it (e.g. `let x = ...`) so a scope cell exists","Check the variable name for typos against the declaration","If the value should be produced by an expression, bind it with `let` instead of assigning","Ensure the assignment is not executed in a scope where the declaration is not visible (e.g. inside a different function/block)"],"exampleFix":"// before (BAML)\nlet count = 0;\ncount = count + 1; // ok\ntotla = count;     // assign to undeclared variable `totla`\n// after\nlet count = 0;\ncount = count + 1;\nlet total = count;","handlingStrategy":"validation","validationCode":"// BAML: ensure the target is declared before assigning\nlet message = \"\";   // declaration creates the scope cell\nmessage = \"hello\";  // now safe","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare every variable with let/params before assigning","Enable editor rename-refactor instead of retyping variable names","Keep scopes shallow so declarations stay visible where assigned"],"tags":["baml","interpreter","assignment","undeclared-variable"],"backgroundTag":"invalid-identifier","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}