clockworklabs/SpacetimeDB · error
Type '%s' contains a circular reference to itself
Error message
Type '%s' contains a circular reference to itself
What it means
Second line of the circular-reference diagnostic, printed right after '[CIRCULAR REFERENCE ERROR] Module cleared and replaced with error type: ...'. It names the exact offending type (g_circular_ref_type_name) that re-entered its own type registration. It is informational detail for error 664 - the fix targets the named type, not this line.
Source
Thrown at crates/bindings-cpp/src/internal/Module.cpp:233
// Create the error type name that indicates the circular reference
std::string error_type_name = "ERROR_CIRCULAR_REFERENCE_" + g_circular_ref_type_name;
// Add a single named type export that points to a non-existent typespace index
// This will cause SpacetimeDB to error when it tries to resolve the type
RawTypeDefV10 error_type;
error_type.source_name.scope = {};
error_type.source_name.source_name = error_type_name;
error_type.ty = 999999; // Invalid typespace index - will cause an error
error_type.custom_ordering = false;
getV10Builder().GetTypeDefs().push_back(error_type);
// Don't add anything to the typespace - this ensures the reference is invalid
// The server will fail with an error message that includes our error type name
// Also log to stderr for debugging
fprintf(stderr, "\n[CIRCULAR REFERENCE ERROR] Module cleared and replaced with error type: %s\n", error_type_name.c_str());
fprintf(stderr, " Type '%s' contains a circular reference to itself\n", g_circular_ref_type_name.c_str());
fflush(stderr);
return; // Exit early, don't check other errors
}
// Check if multiple primary key error occurred during constraint registration
if (g_multiple_primary_key_error) {
// Multiple primary key error detected - create a special error module
// Clear the module state to start fresh.
getV10Builder().Clear();
// Create the error type name
std::string error_type_name = "ERROR_MULTIPLE_PRIMARY_KEYS_" + g_multiple_primary_key_table_name;
// Add a single named type export that points to a non-existent typespace index
// This will cause SpacetimeDB to error when it tries to resolve the type
RawTypeDefV10 error_type;
error_type.source_name.scope = {};View on GitHub (pinned to 6dee26c6ef)
Solutions
- Open the type named in this line and remove the self-reference (replace nested recursive members with row ids)
- If the named type looks non-recursive, check its field types transitively - the cycle may re-enter through a nested container
- Republish after restructuring; the ERROR_CIRCULAR_REFERENCE_* error type disappears once the cycle is gone
Example fix
// before
struct Tree { std::vector<Tree> branches; };
// after
struct Tree { std::vector<uint64_t> branch_ids; }; Defensive patterns
Strategy: validation
Prevention
- Use the type name from this line to jump straight to the offending definition
- Check the named type's fields transitively (containers of containers) for the cycle
- Prefer id-reference patterns for any parent/child linkage between rows
When it happens
Trigger: Always emitted together with the 664 banner whenever g_circular_ref_error is set during type registration; the named type is the one whose registration was re-entered (directly or via a nested field type).
Common situations: Self-referential table column types (tree/graph models); mutually recursive structs both used as table columns.
Related errors
- [CIRCULAR REFERENCE ERROR] Module cleared and replaced with
- Original error: Multiple primary keys detected in table '%s'
- Original error: %s
- [TYPE ERROR] Module cleared and replaced with error type: %
- ERROR: Enum '%s' did not register as a complex type\n
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/d0a69ed890cda640.
Report an issue: GitHub.