BoundaryML/baml · error · ConvertError

Could not add a type to the database as the name `{0}` is al

Error message

Could not add a type to the database as the name `{0}` is already present

What it means

ConvertError::AlreadyPresent(DefKey) is raised in TypeCtx::build_db when TypeRefDb::try_add_inner rejects an insert because a type with the same DefKey was already added. Since classes, enums, and aliases are iterated from distinct maps, this indicates a duplicate name collision in the type database.

Source

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

#[derive(thiserror::Error, Debug)]
pub enum ConvertError {
    #[error("Failed to parse float: {0}")]
    ParseFloat(#[from] std::num::ParseFloatError),
    #[error("Unknown media kind")]
    UnknownMediaKind,
    #[error("Float literals cannot be parsed")]
    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:

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Search your BAML sources for a second declaration of the name in the error and remove or rename one.
  2. Check for the same type name defined in multiple included modules and disambiguate with module-qualified names.
  3. If contexts are merged programmatically, deduplicate definition maps by DefKey before constructing TypeCtx.

Example fix

// before
class User { id: int }
type User = string // collision
// after
class User { id: int }
type UserName = string
Defensive patterns

Strategy: validation

Validate before calling

// Detect duplicate DefKeys across class, enum, and alias maps before build_db
fn assert_no_duplicates(ctx: &TypeCtx) -> Result<(), String> {
    let mut seen = std::collections::HashSet::new();
    for k in ctx.class_definitions.keys()
        .chain(ctx.enum_definitions.keys())
        .chain(ctx.type_alias_definitions.keys()) {
        if !seen.insert(k.clone()) {
            return Err(format!("duplicate type name: {k:?}"));
        }
    }
    Ok(())
}

Try / catch

match result {
    Err(ConvertError::AlreadyPresent(key)) => eprintln!("remove the duplicate declaration of {key:?}"),
    other => other,
}

Prevention

When it happens

Trigger: Calling build_db when two definitions share the same DefKey — e.g. a class and an alias (or two classes) registered under identical keys in the SysOpContext.

Common situations: Duplicate `class Foo` / `type Foo` declarations across loaded modules; merging two contexts that both define the same type name; generated code re-declaring a type that also exists in sources.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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