{"record":{"id":"3130e7d4bc6dccf6","repo":"BoundaryML/baml","slug":"class-name-already-exists","errorCode":null,"errorMessage":"Class ${name} already exists","messagePattern":"Class (.+?) already exists","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"engine/language_client_typescript/type_builder.js","lineNumber":69,"sourceCode":"    }\n    union(types) {\n        return this.tb.union(types);\n    }\n    classViewer(name, properties) {\n        return new ClassViewer(this.tb, name, new Set(properties));\n    }\n    classBuilder(name, properties) {\n        return new ClassBuilder(this.tb, name, new Set(properties));\n    }\n    enumViewer(name, values) {\n        return new EnumViewer(this.tb, name, new Set(values));\n    }\n    enumBuilder(name, values) {\n        return new EnumBuilder(this.tb, name, new Set(values));\n    }\n    addClass(name) {\n        if (this.classes.has(name)) {\n            throw new Error(`Class ${name} already exists`);\n        }\n        if (this.enums.has(name)) {\n            throw new Error(`Enum ${name} already exists`);\n        }\n        this.classes.add(name);\n        return new ClassBuilder(this.tb, name);\n    }\n    addEnum(name) {\n        if (this.classes.has(name)) {\n            throw new Error(`Class ${name} already exists`);\n        }\n        if (this.enums.has(name)) {\n            throw new Error(`Enum ${name} already exists`);\n        }\n        this.enums.add(name);\n        return new EnumBuilder(this.tb, name);\n    }\n    addBaml(baml) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_typescript/type_builder.js#L51-L87","documentation":"TypeBuilder.addClass(name) refuses to add a class whose name is already registered in this JS-side TypeBuilder's class set, throwing this Error. It exists to prevent duplicate class definitions, which would be ambiguous when the builder is compiled into a BAML runtime.","triggerScenarios":"Calling tb.addClass(\"Foo\") twice on the same TypeBuilder instance; rebuilding classes in a loop without a fresh TypeBuilder; a class and enum name collision handled separately (enums throw a different message).","commonSituations":"Hot-reload/dev loops that re-run type-builder setup code against a retained builder; initializing type builders per-request with module-level shared state; accidental duplicate registration from two setup functions.","solutions":["Check tb's registered names (or wrap addClass in a Set-membership check) before calling","Create a new TypeBuilder instance for each rebuild instead of reusing one","Guard registration with a Map so classes are only added once","Wrap addClass in try/catch and ignore the already-exists error if idempotency is intended"],"exampleFix":"// before\nconst names = [\"User\", \"User\"];\nnames.forEach((n) => tb.addClass(n)); // throws on second\n// after\nconst added = new Set();\nnames.forEach((n) => { if (!added.has(n)) { added.add(n); tb.addClass(n); } });","handlingStrategy":"validation","validationCode":"// maintain own registry\nconst registered = new Set();\nfunction addClassOnce(tb, name) { if (!registered.has(name)) { registered.add(name); tb.addClass(name); } }","typeGuard":"null","tryCatchPattern":"try { tb.addClass(name); } catch (e) {\n  if (!String(e.message).startsWith('Class ')) throw e; // ignore duplicate-class only\n}","preventionTips":["Recreate the TypeBuilder on each rebuild/hot-reload","Keep one name registry for classes and enums","Centralize builder setup in a single idempotent function"],"tags":["javascript","type-builder","duplicate","class","baml"],"backgroundTag":"file-already-exists","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}