{"record":{"id":"d7338326b0d7eed6","repo":"BoundaryML/baml","slug":"no-root-state-found-for-local-variable","errorCode":null,"errorMessage":"No root state found for local variable: {:?}","messagePattern":"No root state found for local variable: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"engine/baml-vm/src/test.rs","lineNumber":219,"sourceCode":"\n    pub fn viz(function_name: String, event: VizExecEvent) -> Self {\n        Notification::Viz {\n            function_name,\n            event,\n        }\n    }\n}\n\nimpl Notification {\n    /// Convert from VM NodeId to test Node by resolving indices to names/objects.\n    pub fn from_node_id(node_id: &watch::NodeId, vm: &Vm) -> anyhow::Result<Self> {\n        match node_id {\n            watch::NodeId::LocalVar(stack_index) => vm\n                .watch\n                .root_state(*node_id)\n                .map(|state| Notification::Channel(state.channel.clone()))\n                .ok_or_else(|| {\n                    anyhow::anyhow!(\"No root state found for local variable: {:?}\", stack_index)\n                }),\n            watch::NodeId::HeapObject(_obj_index) => {\n                Ok(Notification::Object(Object::String(\"bogger\".to_string())))\n            }\n        }\n    }\n}\n\n/// Enhanced test execution state that supports test Value comparisons.\n#[derive(Debug, Clone, PartialEq)]\npub enum ExecState {\n    /// VM cannot proceed. It is awaiting a pending future to complete.\n    Await(Object),\n    /// VM notifies caller about a future that needs to be scheduled.\n    ScheduleFuture(Object),\n    /// VM has completed the execution with a test-friendly value.\n    Complete(Value),\n","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-vm/src/test.rs#L201-L237","documentation":"When building a watch Notification for a local-variable node, from_node_id looks up the variable's root state in vm.watch. The map lookup failing means the local variable (by stack index) has no registered root state — i.e. the variable was never put under watch or the state was cleared — yet a notification was requested for it.","triggerScenarios":"Calling from_node_id with NodeId::LocalVar(stack_index) for a variable that has no root state registered in vm.watch (never subscribed, or subscription dropped/cleared before the notification was generated).","commonSituations":"Debugger/watch tooling requesting notifications for stack slots after a frame was popped or before a watch subscription completed; off-by-one stack indices after register allocation changes.","solutions":["Verify the variable was registered via watch before requesting notifications for its NodeId","Check that the stack_index captured when subscribing still matches the current frame layout","Guard the call site so notifications are only fetched for variables with an active root state","Clear pending LocalVar notification requests when watches are unsubscribed or frames are popped"],"exampleFix":"// before\nvm.watch.root_state(*node_id)\n    .map(|state| Notification::Channel(state.channel.clone()))\n    .ok_or_else(|| anyhow::anyhow!(\"No root state found for local variable: {:?}\", stack_index))\n// after\nmatch vm.watch.root_state(*node_id) {\n    Some(state) => Ok(Notification::Channel(state.channel.clone())),\n    None => Ok(Notification::Ignored), // variable is no longer watched\n}","handlingStrategy":"fallback","validationCode":"fn is_watched(vm: &Vm, node: &watch::NodeId) -> bool {\n    vm.watch.root_state_for(node).is_some()\n}","typeGuard":null,"tryCatchPattern":"match Notification::from_node_id(vm, node_id) { Ok(n) => n, Err(_) => Notification::Ignored }","preventionTips":["Register the watch and only then enqueue notification requests","Clean up pending LocalVar notifications when frames are popped or watches unsubscribed","Log stack indices at subscription time and compare with lookup time to catch layout drift"],"tags":["vm","watch","state"],"backgroundTag":"resource-not-found","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"}