BoundaryML/baml · error · Error

Value already exists.

Error message

Value ${name} already exists.

What it means

EnumValueBuilder.addValue throws this when the enum already contains a value with the given name. The builder guards against duplicate enum members because BAML enums require unique value names; adding the same name twice would produce an invalid enum definition. It is a deliberate programmer-error guard, not a runtime condition.

Solutions

  1. Deduplicate the source list before calling addValue, e.g. [...new Set(names)]
  2. Guard each call with a membership check or wrap it in try/catch and skip existing values
  3. Rebuild the TypeBuilder/enum from scratch instead of re-adding values to an existing builder
  4. If the duplicate is intentional (same semantic value from two sources), normalize the source data upstream

Example fix

// before
for (const v of configValues) {
  enumBuilder.addValue(v.name);
}
// after
for (const v of [...new Set(configValues)]) {
  if (!enumBuilder.listValues().some(([n]) => n === v.name)) {
    enumBuilder.addValue(v.name);
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if (enumBuilder.listValues().some(([existing]) => existing === newName)) {
  throw new Error(`Cannot add duplicate enum value: ${newName}`);
}
enumBuilder.addValue(newName);

Prevention

When it happens

Trigger: Calling addValue(name) on an EnumValueBuilder whose underlying values Set already contains name. This happens when the same value name is added twice in a builder chain, or when a loop/config list feeding addValue contains duplicates, or when addValue is called for a name that was passed into the TypeBuilder enum constructor's initial values Set.

Common situations: Building BAML enums dynamically from config files or database rows that contain duplicate entries; merging enum values from two sources without deduplicating; copy-pasted builder code that adds the same literal twice; hot-reload code that re-adds values onto an existing builder without resetting it.

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

Appendix: source

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

    if (!this.values.has(name)) {
      throw new Error(`Value ${name} not found.`)
    }
    return new EnumValueViewer()
  }
}

export class EnumValueViewer {
  constructor() {}
}

export class EnumBuilder<EnumName extends string, T extends string = string> extends EnumAst<EnumName, T> {
  constructor(tb: _TypeBuilder, name: EnumName, values: Set<T | string> = new Set()) {
    super(tb, name, values)
  }

  addValue<S extends string>(name: RestrictNot<EnumName, S, T>): EnumValueBuilder {
    if (this.values.has(name)) {
      throw new Error(`Value ${name} already exists.`)
    }
    this.values.add(name)
    return this.bldr.value(name)
  }

  listValues(): Array<[string, EnumValueBuilder]> {
    return Array.from(this.values).map((name) => [name, this.bldr.value(name)])
  }

  value(name: string): EnumValueBuilder {
    return this.bldr.value(name)
  }
}

View on GitHub (pinned to bd85ce9dee)