BoundaryML/baml · error · Error

Enum ${name} already exists

Error message

Enum ${name} already exists

What it means

TypeBuilder.addClass throws 'Enum <name> already exists' when the requested class name is already taken by a previously registered enum. Classes and enums share one namespace, so addClass refuses names that collide with enums as well as other classes.

Source

Thrown at engine/language_client_typescript/typescript_src/type_builder.ts:113

    properties: Properties[],
  ): ClassBuilder<Name, Properties> {
    return new ClassBuilder(this.tb, name, new Set(properties))
  }

  enumViewer<Name extends string, Values extends string>(name: Name, values: Values[]): EnumViewer<Name, Values> {
    return new EnumViewer(this.tb, name, new Set(values))
  }

  enumBuilder<Name extends string, Values extends string>(name: Name, values: Values[]): EnumBuilder<Name, Values> {
    return new EnumBuilder(this.tb, name, new Set(values))
  }

  addClass<Name extends string>(name: Name): ClassBuilder<Name> {
    if (this.classes.has(name)) {
      throw new Error(`Class ${name} already exists`)
    }
    if (this.enums.has(name)) {
      throw new Error(`Enum ${name} already exists`)
    }
    this.classes.add(name)
    return new ClassBuilder(this.tb, name)
  }

  addEnum<Name extends string>(name: Name): EnumBuilder<Name> {
    if (this.classes.has(name)) {
      throw new Error(`Class ${name} already exists`)
    }
    if (this.enums.has(name)) {
      throw new Error(`Enum ${name} already exists`)
    }
    this.enums.add(name)
    return new EnumBuilder(this.tb, name)
  }

  addBaml(baml: string): void {
    this.tb.addBaml(baml, this.runtime)

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Use a different name for the class or the enum so they do not collide.
  2. Track registered names across helpers and skip re-registration.
  3. Check whether an addEnum call intended to be addClass (or vice versa).

Example fix

// before
tb.addEnum('Status')
tb.addClass('Status') // throws: taken by enum
// after
tb.addEnum('Status')
tb.addClass('StatusRecord') // distinct name
Defensive patterns

Strategy: validation

Validate before calling

// classes and enums share a namespace; check both before registering
if (classNames.has(name) || enumNames.has(name)) throw new Error(`name collision: ${name}`)

Try / catch

try {
  const cls = tb.addClass(name)
} catch (e) {
  if (/Enum .* already exists/.test(e.message)) throw new Error(`'${name}' is registered as an enum; pick another name`)
  throw e
}

Prevention

When it happens

Trigger: Calling typeBuilder.addClass('Status') after typeBuilder.addEnum('Status') was called on the same builder.

Common situations: Merging schemas from multiple sources into one builder where a name exists as both an enum and a class; scripted registration from config files with overlapping names.

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/4717e33d9dc2fc94. Report an issue: GitHub.