{"record":{"id":"182249ad991e717f","repo":"clockworklabs/SpacetimeDB","slug":"error-invalid-type-index-u-for-namespace-update","errorCode":null,"errorMessage":"ERROR: Invalid type index %u for namespace update (max: %zu)\\n","messagePattern":"ERROR: Invalid type index %u for namespace update \\(max: %zu\\)\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/src/internal/module_type_registration.cpp","lineNumber":632,"sourceCode":"            }\n            desc += \"}\";\n            return desc;\n        }\n        \n        case bsatn::AlgebraicTypeTag::Ref:\n            return \"Ref(\" + std::to_string(type.as_ref()) + \")\";\n            \n        default:\n            return \"Unknown(tag=\" + std::to_string(static_cast<int>(type.tag())) + \")\";\n    }\n}\n\nvoid ModuleTypeRegistration::updateTypeNameInModule(uint32_t type_index, const std::string& new_name) {\n    auto& type_defs = getV10Builder().GetTypeDefs();\n    \n    // Check if the type index is valid\n    if (type_index >= type_defs.size()) {\n        fprintf(stderr, \"ERROR: Invalid type index %u for namespace update (max: %zu)\\n\", \n                type_index, type_defs.size());\n        return;\n    }\n    \n    // Parse the new name to extract namespace and name parts\n    auto [scope, name] = parseNamespaceAndName(new_name);\n    \n    // Update the type definition's scoped name\n    type_defs[type_index].source_name.scope = scope;\n    type_defs[type_index].source_name.source_name = name;\n    \n}\n\n// processOptionInnerType function removed - no longer needed\n// Options now use the same LazyTypeRegistrar pattern as other types\n\n} // namespace Internal\n","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-cpp/src/internal/module_type_registration.cpp#L614-L650","documentation":"Printed by ModuleTypeRegistration::updateTypeNameInModule when the type index passed in is >= GetTypeDefs().size(). The index comes from type_name_cache_, populated by registerType()/registerAndGetIndex() with typespace indices, but this function indexes the RawTypeDefV10 array; the update is then silently skipped, so the type keeps its un-namespace-qualified name. It is called from set_type_namespace<T>() in module_type_registration.h:151, which the SPACETIMEDB_NAMESPACE macros invoke during preinit to prepend a namespace to an already-registered type.","triggerScenarios":"A SPACETIMEDB_NAMESPACE(prefix) macro runs for a type whose cached index no longer matches the type-defs array: typespace and type-def arrays have diverged (typespace entries pushed without a matching RawTypeDefV10), a stale type_name_cache_ left over from a previous module build because clear() was not called while the builder was reset (or vice versa), or any path where the typespace grows faster than GetTypeDefs(). Concretely: registering types directly into the typespace (v10_builder pushes) and then using namespace macros on them, or rebuilding a module in the same process without ModuleTypeRegistration::clear().","commonSituations":"Unit tests or host tooling that build a module, reset state, and rebuild in one process; mixed registration styles (macro-based registration plus manual typespace pushes); version transitions of bindings-cpp where the cache/type-def bookkeeping changed shape. The visible symptom is the namespace prefix missing from the published schema (type names without 'Namespace.') plus this stderr line.","solutions":["Ensure every rebuild path calls ModuleTypeRegistration::clear() and resets the V10 builder's typespace and type-def arrays together, so cached indices never outlive the arrays they index (see initializeModuleTypeRegistration at module_type_registration.cpp:28).","Audit for typespace pushes without a matching GetTypeDefs() push: registerComplexType() pushes both (lines 488-499); any other code pushing into GetTypespace().types directly must push a RawTypeDefV10 too, or indices diverge.","Prefer a name-keyed update: change set_type_namespace/updateTypeNameInModule to locate the type-def by source_name instead of by cached index, which is immune to index divergence.","As a guard, bound-check the index at the call site (module_type_registration.h:151) and fail loudly during preinit instead of silently skipping the namespace qualification."],"exampleFix":"// before (module_type_registration.h, set_type_namespace):\n// cached typespace index is used to index the type-def array\nupdateTypeNameInModule(type_index, qualified_name);\n\n// after: resolve the type-def by name so typespace/type-def index\n// divergence cannot produce an out-of-range index\nupdateTypeNameInModule(original_name, qualified_name);\n// (updateTypeNameInModule finds the def via source_name, then rewrites scope/name)","handlingStrategy":"validation","validationCode":"// in set_type_namespace (module_type_registration.h), before updating:\nconst auto& defs = getV10Builder().GetTypeDefs();\nif (type_index >= defs.size()) {\n    // typespace/type-def index divergence or stale cache: do not silently skip\n    fprintf(stderr, \"namespace update for %s skipped: stale index %u (defs: %zu)\\n\",\n            original_name.c_str(), type_index, defs.size());\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register types and apply SPACETIMEDB_NAMESPACE macros in the same preinit pass; never apply namespace macros against a cache from an earlier build.","On every in-process rebuild, call ModuleTypeRegistration::clear() and reset the V10 builder's typespace and type-def arrays together so cached indices cannot outlive the arrays.","Never push entries into GetTypespace().types directly without a matching RawTypeDefV10 push - that is what makes indices diverge.","After module build, assert every published type name carries its expected namespace prefix; a missing prefix is this error's silent symptom."],"tags":["spacetimedb","cpp","type-registration","index-out-of-bounds","namespace"],"backgroundTag":"index-out-of-bounds","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}