clockworklabs/SpacetimeDB · error

[TYPE ERROR] Module cleared and replaced with error type: %

Error message

[TYPE ERROR] Module cleared and replaced with error type: %s

What it means

Banner printed by __preinit__99_validate_types when ModuleTypeRegistration reports hasError(). The module is cleared and replaced by an error type embedding the message (e.g. ERROR_RECURSIVE_TYPE_REFERENCE_<name>) at invalid typespace index 999999; the server then fails module description resolution. Known error messages feeding this path are 'Recursive type reference detected: <type> is referencing itself' and 'Missing type name for complex type...' (toolchain without demangling support, or an anonymous/nested type with no name).

Source

Thrown at crates/bindings-cpp/src/internal/Module.cpp:347

        } else {
            error_type_name = "ERROR_TYPE_REGISTRATION_FAILED";
        }
        
        // 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[TYPE ERROR] Module cleared and replaced with error type: %s\n", error_type_name.c_str());
        fprintf(stderr, "Original error: %s\n\n", error.c_str());
        fflush(stderr);
    }
    //#define DEBUG_TYPE_REGISTRATION
    // Type validation passed - log statistics only in debug mode
    #ifdef DEBUG_TYPE_REGISTRATION
    else {
        fprintf(stderr, "[Type Validation] OK - %zu types, %zu tables, %zu reducers\n",
                getV10Builder().GetTypespace().types.size(),
                getV10Builder().GetTables().size(),
                getV10Builder().GetReducers().size());
    }
    #endif
}


std::vector<uint8_t> Internal::Module::SerializeModuleDef() {
    RawModuleDefV10 v10_module = getV10Builder().BuildModuleDef();

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Read the 'Original error:' line printed right after the banner - it contains the exact registration error and type name
  2. For 'Recursive type reference' - break the cycle by referencing rows by id or using indirection
  3. For 'Missing type name' - give the complex type a concrete named struct and register it explicitly (registerTypeByName / explicit type-name macro) instead of relying on demangling
  4. Verify you are on a supported toolchain where type-name demangling is enabled

Example fix

// before
struct Item {
  std::vector<Item> children; // recursive -> 'Recursive type reference'
};

// after
struct Item {
  std::vector<uint64_t> child_ids;
};
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: A type re-entering registerType while still being registered (types_being_registered_ cycle detection fires); a complex type (e.g. a nested struct used as a column) whose name cannot be determined because typeid-based demangling is unavailable or the type is anonymous.

Common situations: Using unnamed/anonymous structs or lambdas-captured types as table columns; building with a toolchain where typeid(...).name() is mangled and demangling support is off; recursive types that evade the earlier g_circular_ref_error path.

Related errors


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