BoundaryML/baml · error · Error
Property ${name} already exists.
Error message
Property ${name} already exists. What it means
ClassBuilder.addProperty throws when a property with the same name has already been added to the class. The builder tracks property names in a Set and rejects duplicates so the generated BAML class has unique fields.
Source
Thrown at engine/language_client_typescript/typescript_src/type_builder.ts:185
property(name: string): ClassPropertyViewer {
if (!this.properties.has(name)) {
throw new Error(`Property ${name} not found.`)
}
return new ClassPropertyViewer()
}
}
export class ClassBuilder<ClassName extends string, Properties extends string = string> extends ClassAst<
ClassName,
Properties
> {
constructor(tb: _TypeBuilder, name: ClassName, properties: Set<Properties | string> = new Set()) {
super(tb, name, properties)
}
addProperty<S extends string>(name: RestrictNot<ClassName, S, Properties>, type: FieldType): ClassPropertyBuilder {
if (this.properties.has(name)) {
throw new Error(`Property ${name} already exists.`)
}
this.properties.add(name)
return new ClassPropertyBuilder(this.bldr.property(name).setType(type))
}
listProperties(): Array<[string, ClassPropertyBuilder]> {
return (this.bldr.listProperties() as Array<[string, _ClassPropertyBuilder]>).map(
([name, prop]) => [name, new ClassPropertyBuilder(prop)],
)
}
removeProperty(name: string): void {
this.properties.delete(name)
this.bldr.removeProperty(name)
}
reset(): void {
this.bldr.reset()View on GitHub (pinned to bd85ce9dee)
Solutions
- Skip addProperty when the name is already present (check your own registry or listProperties).
- Use the returned property builder to update the type instead of re-adding.
- Recreate the ClassBuilder if stale state accumulates across rebuilds.
Example fix
// before
classBuilder.addProperty('id', t.string())
classBuilder.addProperty('id', t.int()) // throws
// after
if (!addedProps.has('id')) { classBuilder.addProperty('id', t.string()); addedProps.add('id') } Defensive patterns
Strategy: validation
Validate before calling
if (classBuilder.listProperties().some(([n]) => n === name)) return // already added classBuilder.addProperty(name, type)
Try / catch
try {
classBuilder.addProperty(name, type)
} catch (e) {
if (e.message.includes('already exists')) return
throw e
} Prevention
- Deduplicate input field definitions (e.g. by object key) before mapping to addProperty.
- Build classes once at module init, not per-request without reset.
- Track added properties in a Set alongside the builder.
When it happens
Trigger: Calling classBuilder.addProperty('title', ...) twice on the same ClassBuilder, or a loop mapping object keys to properties that runs twice (e.g. retry or merge path).
Common situations: Merging two JSON schemas that share field names; building a class once at module load and again in a hot-reload callback.
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
- Class ${name} already exists
- Enum with name {name} already exists
- Class with name {name} already exists
- Enum ${name} already exists
- Property ${name} not found.
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/d24db87e6c8f32a0.
Report an issue: GitHub.