BoundaryML/baml · error · anyhow::Error

Recursive alias {name} not found

Error message

Recursive alias {name} not found

What it means

find_recursive_alias_target resolves a structurally recursive type alias to its TypeIR target from the precomputed structural_recursive_aliases map. The error means an alias name expected to be recursive was not registered in that map. It is an internal resolution failure rather than a user-input parse failure.

Source

Thrown at engine/baml-lib/jinja-runtime/src/output_format/types.rs:1080

}

impl OutputFormatContent {
    pub fn find_enum(&self, name: &str) -> Result<&Enum> {
        self.enums
            .get(name)
            .ok_or_else(|| anyhow::anyhow!("Enum {name} not found"))
    }

    pub fn find_class(&self, mode: &baml_types::StreamingMode, name: &str) -> Result<&Class> {
        self.classes
            .get(&(name.to_string(), *mode))
            .ok_or_else(|| anyhow::anyhow!("Class {name} not found"))
    }

    pub fn find_recursive_alias_target(&self, name: &str) -> Result<&TypeIR> {
        self.structural_recursive_aliases
            .get(name)
            .ok_or_else(|| anyhow::anyhow!("Recursive alias {name} not found"))
    }
}

#[cfg(test)]
mod tests {
    use std::vec;

    use baml_types::ir_type::UnionConstructor;

    use super::*;

    #[test]
    fn render_string() {
        let content = OutputFormatContent::new_string();
        let rendered = content.render(RenderOptions::default()).unwrap();
        assert_eq!(rendered, None);
    }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Confirm the alias actually refers to a structurally recursive type in your .baml schema.
  2. Regenerate/re-analyze the schema so structural_recursive_aliases is rebuilt from the current definitions.
  3. Check that callers only query aliases that passed a recursive-alias check earlier in resolution.
  4. If it occurs during valid resolution, report as a BAML internal bug with the schema snippet.

Example fix

// before: treating non-recursive alias as recursive
let t = of.find_recursive_alias_target("Tree")?;
// after: define a genuinely recursive alias in .baml
// alias Tree = int | Tree[] | { node: Tree }
Defensive patterns

Strategy: type-guard

Validate before calling

// only query aliases already classified as structurally recursive
if !output_format.structural_recursive_aliases.contains_key(alias_name) {
    // fall back to normal type resolution instead of the recursive path
}

Type guard

fn is_recursive_alias(of: &OutputFormatContent, name: &str) -> bool {
    of.structural_recursive_aliases.contains_key(name)
}

Try / catch

match of.find_recursive_alias_target(name) {
    Ok(t) => use_target(t),
    Err(err) => resolve_non_recursive(name).or_else(|_| Err(err)),
}

Prevention

When it happens

Trigger: Calling find_recursive_alias_target(name) for an alias that is not in structural_recursive_aliases — i.e. the alias either does not exist, is not actually structurally recursive, or the analysis pass that populates the map was skipped/out of date.

Common situations: Schema edits that turned a recursive alias into a non-recursive one while code still treats it as recursive; internal resolution ordering bugs; partially regenerated clients mixing old and new type graphs.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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