BoundaryML/baml · error

Type not found for property {} in class {}

Error message

Type not found for property {} in class {}

What it means

Thrown by ClassPropertyBuilder::type_() when neither the type-builder property nor the AST/IR definition carries a type for the property. The method tries builder.r#type() first and falls back to the AST type; if both are None it reports that no type could be resolved for the property.

Source

Thrown at engine/language_client_cffi/src/raw_ptr_wrapper/type_builder/objects.rs:486

        Ok(result)
    }

    pub fn type_(&self, rt: &BamlRuntime) -> Result<TypeIR, anyhow::Error> {
        self.mode.at_least(NodeRW::ReadOnly)?;

        let ast_type = || {
            if let Ok(cls) = rt.ir.find_class(self.class_name.as_str()) {
                cls.find_field(&self.property_name)
                    .map(|field| field.r#type().clone())
            } else {
                None
            }
        };

        let prop = self.prop(rt)?;
        let builder = prop.lock().unwrap();
        let result = builder.r#type().or_else(ast_type).ok_or_else(|| {
            anyhow::anyhow!(
                "Type not found for property {} in class {}",
                self.property_name,
                self.class_name
            )
        });
        result
    }

    pub fn set_description(&self, rt: &BamlRuntime, description: &str) -> anyhow::Result<()> {
        self.mode.at_least(NodeRW::LLMOnly)?;

        let prop = self.prop(rt)?;
        let builder = prop.lock().unwrap();
        builder.with_meta("description", BamlValue::String(description.to_string()));
        Ok(())
    }

    pub fn set_alias(&self, rt: &BamlRuntime, alias: &str) -> anyhow::Result<()> {

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Call set_type(...) on the property builder before reading type_().
  2. Use ClassBuilder::add_property(name, field_type) which sets the type atomically instead of a bare upsert.
  3. Check that the .baml class field actually declares a type.
  4. Read the type only after the type-builder graph is fully constructed.

Example fix

// before
let prop = tb.class("Foo").property("bar");
let t = prop.type_(rt)?; // type never set
// after
let prop = tb.class("Foo").add_property("bar", FieldType::string())?;
let t = prop.type_(rt)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the type is set before reading it:
let prop = tb.class("Foo").property("bar");
// if you created it dynamically, call add_property(name, ty) rather than a bare upsert

Try / catch

let ty = match prop.type_(rt) {
    Ok(t) => t,
    Err(e) if e.to_string().contains("Type not found") => set_default_type_then_read()?,
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: Calling .type_(rt) on a property that was upserted (e.g. via add_property or prop()) but whose TypeIR was never set, on a property that exists in the builder graph without a type, or on an IR property whose type is somehow absent.

Common situations: dynamically upserting a property without calling set_type(); partially constructed type builders; reading the type of a freshly created property before assignment.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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