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

  1. Open the type named in this line and remove the self-reference (replace nested recursive members with row ids)
  2. If the named type looks non-recursive, check its field types transitively - the cycle may re-enter through a nested container
  3. 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

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


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/d0a69ed890cda640. Report an issue: GitHub.