{"record":{"id":"0600a8f1cb852858","repo":"clockworklabs/SpacetimeDB","slug":"missing-type-name-for-typebuilder-constructor-na","errorCode":null,"errorMessage":"Missing type name for ${typeBuilder.constructor.name ?? 'TypeBuilder'} ${JSON.stringify(typeBuilder)}","messagePattern":"Missing type name for (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/lib/schema.ts","lineNumber":361,"sourceCode":"      ) as any;\n    } else {\n      return typeBuilder as any;\n    }\n  }\n\n  #registerCompoundTypeRecursively<\n    T extends\n      | SumBuilder<VariantsObj>\n      | ProductBuilder<ElementsObj>\n      | RowBuilder<RowObj>,\n  >(typeBuilder: T): RefBuilder<Infer<T>, InferSpacetimeTypeOfTypeBuilder<T>> {\n    const ty = typeBuilder.algebraicType;\n    // NB! You must ensure that all TypeBuilder passed into this function\n    // have a name. This function ensures that nested types always have a\n    // name by assigning them one if they are missing it.\n    const name = typeBuilder.typeName;\n    if (name === undefined) {\n      throw new Error(\n        `Missing type name for ${typeBuilder.constructor.name ?? 'TypeBuilder'} ${JSON.stringify(typeBuilder)}`\n      );\n    }\n\n    let r = this.#compoundTypes.get(ty);\n    if (r != null) {\n      // Already added to typespace\n      return r;\n    }\n\n    // Recursively register nested compound types\n    const newTy =\n      typeBuilder instanceof RowBuilder || typeBuilder instanceof ProductBuilder\n        ? ({\n            tag: 'Product',\n            value: { elements: [] },\n          } as AlgebraicTypeVariants.Product)\n        : ({","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-typescript/src/lib/schema.ts#L343-L379","documentation":"SchemaBuilder's #registerCompoundTypeRecursively inserts compound types into the typespace so nested and recursive types can be referenced by Ref. Its documented contract (see the NB comment) is that callers only pass builders that already carry a typeName; a top-level anonymous builder would generate types the codegen cannot name or reference, so it fails fast with the builder's constructor name and a JSON dump.","triggerScenarios":"Registering an anonymous builder - t.object({...}) or t.enum({...}) with no first name argument - through a schema-builder path that does not auto-assign nested names; calling the schema registration internals directly with inline builders.","commonSituations":"Refactoring type-builder declarations and dropping the name argument; moving a nested anonymous type into a top-level registration slot; copy-pasting a builder literal that never had a name.","solutions":["Give the type a name: t.object('Player', {...}) or t.enum('Status', {...})","Keep anonymous builders for nested positions only; anything registered at top level must be named","Use the error's constructor.name and JSON dump to locate which builder was anonymous"],"exampleFix":"// before\nconst player = t.object({ name: t.string, hp: t.u32 }); // anonymous at registration -> throws\n\n// after\nconst player = t.object('Player', { name: t.string, hp: t.u32 });","handlingStrategy":"validation","validationCode":"function assertNamedBuilder(b: { typeName?: unknown; constructor: { name: string } }): void {\n  if (b.typeName === undefined) {\n    throw new Error(`refusing to register anonymous ${b.constructor.name}: give it a name`);\n  }\n}","typeGuard":"function isNamedBuilder<T extends { typeName?: string }>(b: T): b is T & { typeName: string } {\n  return b.typeName !== undefined;\n}","tryCatchPattern":null,"preventionTips":["Name every top-level type builder: t.object('Player', {...}), t.enum('Status', {...})","Reserve anonymous builders for nested positions only","Lint for t.object(/t.enum( calls whose first argument is not a string at top level"],"tags":["schema","type-builder","spacetimedb","typescript","codegen"],"backgroundTag":"anonymous-schema-type","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}