{"record":{"id":"7c0a43fc8c115941","repo":"BoundaryML/baml","slug":"property-name-already-exists","errorCode":null,"errorMessage":"Property ${name} already exists.","messagePattern":"Property (.+?) already exists\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"engine/language_client_typescript/type_builder.js","lineNumber":128,"sourceCode":"    }\n    listProperties() {\n        return Array.from(this.properties).map((name) => [name, new ClassPropertyViewer()]);\n    }\n    property(name) {\n        if (!this.properties.has(name)) {\n            throw new Error(`Property ${name} not found.`);\n        }\n        return new ClassPropertyViewer();\n    }\n}\nexports.ClassViewer = ClassViewer;\nclass ClassBuilder extends ClassAst {\n    constructor(tb, name, properties = new Set()) {\n        super(tb, name, properties);\n    }\n    addProperty(name, type) {\n        if (this.properties.has(name)) {\n            throw new Error(`Property ${name} already exists.`);\n        }\n        this.properties.add(name);\n        return new ClassPropertyBuilder(this.bldr.property(name).setType(type));\n    }\n    listProperties() {\n        return this.bldr.listProperties().map(([name, prop]) => [name, new ClassPropertyBuilder(prop)]);\n    }\n    removeProperty(name) {\n        this.properties.delete(name);\n        this.bldr.removeProperty(name);\n    }\n    reset() {\n        this.bldr.reset();\n    }\n    property(name) {\n        if (!this.properties.has(name)) {\n            throw new Error(`Property ${name} not found.`);\n        }","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_typescript/type_builder.js#L110-L146","documentation":"ClassBuilder.addProperty(name, type) throws when a property with the same name was already added to this builder, preventing duplicate fields in the generated class. The builder tracks names in a Set and rejects the second registration.","triggerScenarios":"Calling addProperty(\"x\", ...) twice on the same ClassBuilder; loops that add properties from data containing duplicate keys; re-running builder construction on a retained builder instance.","commonSituations":"Building classes from JSON samples where keys repeat across merged objects; hot-reload re-running schema setup; overwriting a field's type by re-adding it (not supported — must rebuild).","solutions":["Skip the add if the property already exists, or rebuild the class with corrected types","Deduplicate source keys (e.g. Object.entries on a merged object is already unique — check your iteration logic)","Use a fresh ClassBuilder when the schema changes instead of mutating in place","Wrap addProperty in try/catch to ignore intentional duplicates"],"exampleFix":"// before\ncb.addProperty(\"id\", \"string\");\ncb.addProperty(\"id\", \"int\"); // throws\n// after\ncb.addProperty(\"id\", \"int\"); // decide one type; duplicates not allowed","handlingStrategy":"validation","validationCode":"const seenProps = new Set();\nfunction addPropOnce(cb, name, type) { if (!seenProps.has(name)) { seenProps.add(name); cb.addProperty(name, type); } }","typeGuard":"null","tryCatchPattern":"try { cb.addProperty(name, type); } catch (e) {\n  if (String(e.message).includes('already exists')) { /* skip or rebuild */ }\n  else throw e;\n}","preventionTips":["Deduplicate keys before iterating source data into properties","Use a fresh ClassBuilder when a field type must change","Centralize class construction in idempotent setup code"],"tags":["javascript","type-builder","duplicate","property","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"}