BoundaryML/baml · error · ConvertError

Recursive type alias without indirection: {0}

Error message

Recursive type alias without indirection: {0}

What it means

ConvertError::DirectRecursiveTypeAlias(DefKey) is raised when a type alias directly contains a reference to itself (or chains to itself) with no indirection — e.g. `type A = B; type B = A;` or `type A = A;`. Such aliases are invalid because the recursion is not broken by a container like a list or an optional.

Source

Thrown at baml_language/crates/bex_sap/src/sap_model/convert.rs:47

    FloatLiteral,
    #[error("Non-parsable type: {0:?}")]
    NonParsableType(Box<SapTy>),
    #[error("Unknown class: {0}")]
    UnknownClass(DefKey),
    #[error("Unknown enum: {0}")]
    UnknownEnum(DefKey),
    #[error("Unknown type alias: {0}")]
    UnknownTypeAlias(DefKey),
    #[error("Unknown name (could not determine if it was a class, enum, or type alias): {0}")]
    UnknownName(DefKey),
    #[error("Could not add a type to the database as the name `{0}` is already present")]
    AlreadyPresent(DefKey),
    #[error("Recursion depth exceeded for {0}")]
    RecursionDepthExceeded(&'static str),
    #[error("Unions must be flattened")]
    UnflattenedUnion,
    /// Something like `type A = B; type B = A;` is invalid.
    #[error("Recursive type alias without indirection: {0}")]
    DirectRecursiveTypeAlias(DefKey),
    #[error("Internal error (please report): {0}")]
    InternalError(&'static str),
}

const MAX_RECURSION_DEPTH: usize = 16;

/// Contains stuff from [`sys_types::SysOpContext`] that we need for converting to the sap model.
///
/// ## Representation
/// - Unions should be flattened:
///   - Union members cannot be unions
///   - Union members cannot be optional
///   - Union members cannot be type aliases which themselves resolve to unions (or optionals)
///   - Same rules for the inner type of an optional type
/// - Type aliases should be flattened:
///   - Type aliases cannot directly contain the name of another type alias (or itself)
///   - example: `type A = int; type B = A;` is invalid (`B` should be updated to directly reference `int`)

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Break the cycle by adding indirection — wrap the recursive reference in a list or optional, e.g. type A = A[] | null.
  2. Replace the cyclic alias pair with a class: recursive classes like class Tree { children: Tree[] } are allowed.
  3. Review the two alias declarations named in your sources and remove the direct cycle.

Example fix

// before
type A = B
type B = A
// after
class A { next: A? } // recursion via class with optional indirection
Defensive patterns

Strategy: validation

Validate before calling

// Detect aliases that reference themselves directly
fn is_directly_recursive(defs: &HashMap<DefKey, SapTy>, key: &DefKey) -> bool {
    let mut cur = key.clone();
    for _ in 0..16 {
        match defs.get(&cur) {
            Some(SapTy::TypeAlias(next, _)) => {
                if next == key { return true; }
                cur = next.clone();
            }
            _ => return false,
        }
    }
    false
}

Try / catch

match result {
    Err(ConvertError::DirectRecursiveTypeAlias(key)) => eprintln!("alias {key:?} recurses without indirection — add [] or ?"),
    other => other,
}

Prevention

When it happens

Trigger: convert_ty's alias-flattening loop encounters SapTy::TypeAlias(name) whose name equals the alias currently being flattened; convert_type_alias also reports this shape as RecursionDepthExceeded for self-reference without indirection.

Common situations: Mutually recursive alias declarations (`type A = B; type B = A;`); a copy-paste typo making an alias reference itself; generated code emitting cyclic aliases.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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