BoundaryML/baml · error · RenderError

Non-regular recursive generic class '{class}' expands from '

Error message

Non-regular recursive generic class '{class}' expands from '{ancestor}' to '{instantiation}'

What it means

BAML emits this error while expanding a recursive generic class into its output schema. A recursive generic is 'non-regular' if the generic parameters change shape across recursion levels — e.g. a class instantiating its own ancestor with different type arguments than the fixed point requires. The compiler refuses to expand it because the expansion would diverge or produce an infinite/unrepresentable type.

Source

Thrown at baml_language/crates/sys_ops/src/output_format.rs:17

use std::fmt::Write as _;

use ::sys_types::SapTy;
use baml_base::Literal as LiteralValue;
use indexmap::IndexMap;
use thiserror::Error;

/// Error type for output format rendering.
#[derive(Clone, Debug, Error)]
pub enum RenderError {
    #[error("Enum '{0}' not found")]
    EnumNotFound(String),
    #[error("Class '{0}' not found")]
    ClassNotFound(String),
    #[error("Type '{0}' is not supported in outputs")]
    UnsupportedType(String),
    #[error(
        "Non-regular recursive generic class '{class}' expands from '{ancestor}' to '{instantiation}'"
    )]
    NonRegularRecursiveGeneric {
        class: String,
        ancestor: String,
        instantiation: String,
    },
    #[error(
        "Output definitions '{first}' and '{second}' both render as '{rendered_name}' in the output schema"
    )]
    RenderedClassNameCollision {
        rendered_name: String,
        first: String,
        second: String,
    },
    #[error(
        "Output definitions '{first}' and '{second}' both render as '{rendered_name}' in the output schema"
    )]

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Make the recursive instantiation regular: ensure the class references its ancestor with the exact same type arguments as the original declaration
  2. Break the recursion by introducing a base case class or optional field so expansion terminates
  3. Replace the recursive generic with a concrete (non-generic) recursive type or an alias if parameterization isn't needed

Example fix

// before
class Node<T> { child Node<Node<T>> }
// after
class Node { child Node? }
Defensive patterns

Strategy: validation

Validate before calling

fn is_regular_recursive(class: &ClassDef) -> bool {
    class.type_params.iter().all(|tp| class.uses_ancestor_with_same_args(tp))
}
if !is_regular_recursive(&my_class) { /* fix instantiation before generating schema */ }

Prevention

When it happens

Trigger: Declaring a BAML class that recursively references itself or an ancestor generic class with a different type instantiation than the regular fixed point; the expansion loop detects the mismatch between the ancestor's declaration and the new instantiation and raises this variant of OutputFormatError.

Common situations: Modeling recursive trees/linked lists in BAML schema with generics; typo in a type argument so the recursive instantiation doesn't match the original; attempting mutual recursion through generic parameters.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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