BoundaryML/baml · error

Variable ' ' not found for $watch.notify()

Error message

Variable '{}' not found for $watch.notify()

What it means

The BAML interpreter's $watch.notify() mechanism looks up the named variable in the current scope chain to fire a watch notification. If the variable is not found in any scope, the interpreter returns an error instead of notifying. This means the watch target referenced in the notify call no longer exists (or never existed) in the executing scope.

Solutions

  1. Correct the variable name passed to $watch.notify to match a variable in the current scope
  2. Move the notify call into the same block/scope where the variable is declared
  3. Declare the variable before the notify call executes
  4. Verify @watch registration happened for that variable (register_watch_variable) before notifying

Example fix

// before
$watch.notify(watchedVale)
// after
$watch.notify(watchedValue)
Defensive patterns

Strategy: validation

Validate before calling

fn validate_watch_target(var: &str, scopes: &[Scope]) -> Result<(), String> {
    if scopes.iter().rev().any(|s| s.contains(var)) { Ok(()) }
    else { Err(format!("'{}' not in scope for $watch.notify", var)) }
}

Type guard

fn is_in_scope(name: &str, scopes: &[Scope]) -> bool { scopes.iter().rev().any(|s| s.contains(name)) }

Prevention

When it happens

Trigger: Executing $watch.notify(some_var) (or equivalent watch handling in handle_statement) where some_var is not registered in the active scopes — e.g. notifying inside a block where the variable was never declared, after it went out of scope, or with a misspelled name.

Common situations: Typo in the variable passed to $watch.notify; calling notify from a helper block where the watched variable is out of scope; renaming a watched variable without updating notify calls.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/4235944acf738665. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-compiler/src/thir/interpret.rs:158

                .watch_variables
                .iter()
                .find(|wv| Arc::ptr_eq(&wv.value_ref, value_ref))
                .map(|wv| wv.spec.name.clone())
                .unwrap_or_else(|| var_name.to_string());

            let current_value = value_ref.lock().unwrap();
            let watch_value = expr_value_to_watch_value(current_value.clone());
            let notification = crate::watch::WatchNotification::new_var(
                var_name.to_string(), // variable name
                channel_name,         // current channel name from WatchSpec
                watch_value,
                function_name.to_string(),
            );
            watch_handler.lock().unwrap().notify(notification);
            return Ok(());
        }
    }
    bail!("Variable '{}' not found for $watch.notify()", var_name)
}

enum EvalValue {
    Value(BamlValueWithMeta<ExprMetadata>),
    Reference(Arc<Mutex<BamlValueWithMeta<ExprMetadata>>>),
    Function(usize, Arc<Block<ExprMetadata>>, ExprMetadata),
}

#[derive(Debug)]
enum ControlFlow {
    Normal(BamlValueWithMeta<ExprMetadata>),
    Break,
    Continue,
    Return(BamlValueWithMeta<ExprMetadata>),
}

/// Check all @watch variables for changes and fire notifications
///

View on GitHub (pinned to bd85ce9dee)