{"record":{"id":"f7d7479ac857878a","repo":"clockworklabs/SpacetimeDB","slug":"circular-reference-error-module-cleared-and-rep","errorCode":null,"errorMessage":"\n[CIRCULAR REFERENCE ERROR] Module cleared and replaced with error type: %s\n","messagePattern":"\n\\[CIRCULAR REFERENCE ERROR\\] Module cleared and replaced with error type: (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/src/internal/Module.cpp","lineNumber":232,"sourceCode":"        \n        // Create the error type name that indicates the circular reference\n        std::string error_type_name = \"ERROR_CIRCULAR_REFERENCE_\" + g_circular_ref_type_name;\n        \n        // Add a single named type export that points to a non-existent typespace index\n        // This will cause SpacetimeDB to error when it tries to resolve the type\n        RawTypeDefV10 error_type;\n        error_type.source_name.scope = {};\n        error_type.source_name.source_name = error_type_name;\n        error_type.ty = 999999; // Invalid typespace index - will cause an error\n        error_type.custom_ordering = false;\n        \n        getV10Builder().GetTypeDefs().push_back(error_type);\n        \n        // Don't add anything to the typespace - this ensures the reference is invalid\n        // The server will fail with an error message that includes our error type name\n        \n        // Also log to stderr for debugging\n        fprintf(stderr, \"\\n[CIRCULAR REFERENCE ERROR] Module cleared and replaced with error type: %s\\n\", error_type_name.c_str());\n        fprintf(stderr, \"  Type '%s' contains a circular reference to itself\\n\", g_circular_ref_type_name.c_str());\n        fflush(stderr);\n        return; // Exit early, don't check other errors\n    }\n    \n    // Check if multiple primary key error occurred during constraint registration\n    if (g_multiple_primary_key_error) {\n        // Multiple primary key error detected - create a special error module\n        \n        // Clear the module state to start fresh.\n        getV10Builder().Clear();\n        \n        // Create the error type name\n        std::string error_type_name = \"ERROR_MULTIPLE_PRIMARY_KEYS_\" + g_multiple_primary_key_table_name;\n        \n        // Add a single named type export that points to a non-existent typespace index\n        // This will cause SpacetimeDB to error when it tries to resolve the type\n        RawTypeDefV10 error_type;","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-cpp/src/internal/Module.cpp#L214-L250","documentation":"Banner printed by __preinit__99_validate_types when the global g_circular_ref_error flag was set while building the module typespace. The entire module is cleared and replaced by a single error type named ERROR_CIRCULAR_REFERENCE_<type> pointing at invalid typespace index 999999, which makes the server fail module description resolution; this stderr banner is the module-side diagnostic for that publish failure.","triggerScenarios":"A type registered in a table/reducer/view references itself through the registration machinery - e.g. struct A containing std::vector<A> members whose field types re-enter registerType for the same type name while it is still being registered; mutual recursion A -> B -> A across table column types.","commonSituations":"Modeling graphs, trees or linked lists as nested value types instead of table rows; porting C++ domain types unchanged and marking them as table columns.","solutions":["Locate the type named in the banner and break the cycle: replace self-referencing members with row-id references (uint64_t foreign keys into another table)","Use supported indirection (Box/unique_ptr-style wrapper) for recursive structure if the bindings version supports it","Hoist the recursive payload into its own table and reference it by id from both sides"],"exampleFix":"// before\nstruct Node {\n  std::string label;\n  std::vector<Node> children; // re-enters registration for 'Node'\n};\n\n// after\nstruct Node {\n  std::string label;\n  std::vector<uint64_t> child_ids; // reference rows by id\n};","handlingStrategy":"validation","validationCode":"// host-side smoke test: run module init and inspect the description\n// (call __describe_module__ in a test harness) and assert no error types\n// for (auto& td : typeDefs)\n//   assert(td.source_name.source_name.rfind(\"ERROR_\", 0) != 0);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model recursive structures as rows plus id references, not nested value types","Review new table columns for types that transitively contain themselves","Run a describe-module smoke test in CI to catch ERROR_CIRCULAR_REFERENCE_* types before deploy"],"tags":["spacetimedb","cpp","types","circular-reference","schema"],"backgroundTag":"recursive-type-definition","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}