BoundaryML/baml · critical

getattr(Checked)

Error message

getattr(Checked)

What it means

pythonize_strict looks up the Checked generic class on the response's class module with cls_module.getattr("Checked") and unwraps with expect("getattr(Checked)"). Panic means the generated BAML client module does not define Checked, so checked fields cannot be typed.

Solutions

  1. Regenerate baml_client (baml-cli generate) so the module exports Checked
  2. Upgrade baml-py/engine to matching versions
  3. Ensure the class module passed to parsing is the generated baml_client module, not an arbitrary one
  4. Reinstall the baml package if Checked is missing from baml_py

Example fix

// before
# stale generated client without Checked
import old_baml_client as cls_module
// after
baml-cli generate
from baml_client import baml_module as cls_module
Defensive patterns

Strategy: validation

Validate before calling

import baml_client
assert hasattr(baml_client, "Checked"), "regenerate baml_client: baml-cli generate"

Type guard

def client_has_checked(mod) -> bool:
    return hasattr(mod, "Checked")

Prevention

When it happens

Trigger: Parsing a response with checks when the generated client module (cls_module) is stale — generated before checks/Checked were supported — or module wasn't imported correctly.

Common situations: Out-of-date generated baml_client after upgrading the engine; custom modules passed as the class module that lack Checked; partially generated client code.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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

Appendix: source

Thrown at engine/language_client_python/src/types/function_results.rs:326

    let literal = typing.getattr("Literal").expect("Literal");

    let value_with_possible_checks = if !checks.is_empty() {
        // Generate the Python checks
        let python_checks = pythonize_checks(py, cls_module, &checks, model_validate_method)
            .expect("pythonize_checks");

        // Get the type of the original value
        let value_type = py_value_without_constraints.bind(py).get_type();

        // Collect check names as &str and turn them into a Python tuple
        let check_names: Vec<&str> = checks.iter().map(|check| check.name.as_str()).collect();
        let literal_args = PyTuple::new(py, check_names)?;

        // Call Literal[...] dynamically
        let literal_check_names = literal.get_item(literal_args).expect("get_item");

        let class_checked_type_constructor =
            cls_module.getattr("Checked").expect("getattr(Checked)");

        // Prepare type parameters for Checked[...]
        let type_parameters_tuple =
            PyTuple::new(py, [value_type.as_ref(), &literal_check_names]).expect("PyTuple::new");

        // Create the Checked type using __class_getitem__
        let class_checked_type: Bound<'_, PyAny> = class_checked_type_constructor
            .call_method1("__class_getitem__", (type_parameters_tuple,))
            .expect("__class_getitem__");

        // Prepare the properties dictionary
        let properties_dict = pyo3::types::PyDict::new(py);
        properties_dict.set_item("value", py_value_without_constraints)?;
        if !checks.is_empty() {
            properties_dict.set_item("checks", python_checks)?;
        }

        // Validate the model with the constructed type

View on GitHub (pinned to bd85ce9dee)