clockworklabs/SpacetimeDB · error

NO_SUCH_PROCEDURE

NO_SUCH_PROCEDURE

Error message

ERROR: Invalid procedure ID %u (have %zu procedures)\n

What it means

Dispatch guard in Module::__call_procedure__: the host called a procedure by numeric ID >= g_procedure_handlers.size(). The function logs the message and returns -1 (NO_SUCH_PROCEDURE). The procedure handler table registered at init does not cover the ID the server derived from the published module description.

Source

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

    // Call the view handler - returns fully serialized result data, including the header byte.
    std::vector<uint8_t> result_data = handler_info.handler(ctx, args_source);
    WriteBytes(result_sink, result_data);
    
    return 2;  // Success with data
}

// Dispatch function for procedures
int16_t Module::__call_procedure__(
    uint32_t id,
    uint64_t sender_0, uint64_t sender_1, uint64_t sender_2, uint64_t sender_3,
    uint64_t conn_id_0, uint64_t conn_id_1,
    uint64_t timestamp_microseconds,
    BytesSource args_source,
    BytesSink result_sink
) {
    // Check if procedure ID is valid
    if (id >= g_procedure_handlers.size()) {
        fprintf(stderr, "ERROR: Invalid procedure ID %u (have %zu procedures)\n", 
                id, g_procedure_handlers.size());
        return -1;  // NO_SUCH_PROCEDURE
    }
    
    // Create sender identity from the 4 uint64_t parts
    std::array<uint8_t, 32> sender_bytes{};
    std::memcpy(sender_bytes.data(), &sender_0, 8);
    std::memcpy(sender_bytes.data() + 8, &sender_1, 8);
    std::memcpy(sender_bytes.data() + 16, &sender_2, 8);
    std::memcpy(sender_bytes.data() + 24, &sender_3, 8);
    
    Identity sender_identity(sender_bytes);
    
    // Create timestamp from microseconds
    Timestamp timestamp = Timestamp::from_micros_since_epoch(
        static_cast<int64_t>(timestamp_microseconds));
    
    // Create connection ID from the two 64-bit parts (full 128-bit value)

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Republish the module so procedure IDs and handlers line up
  2. Keep procedure registration macros unconditional
  3. Verify server logs show a clean module init (no skipped preinit steps)
  4. Regenerate client bindings after procedure schema changes

Example fix

// before
#if WITH_PROCEDURES
PROCEDURE(compute) { /* ... */ }
#endif

// after
PROCEDURE(compute) { /* ... */ } // always registered
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Procedure registration macros conditionally compiled or skipped during a partially failed init; stale binary vs. server metadata after adding/removing procedures; publishing a module whose description and wasm disagree.

Common situations: Version skew between module builds; refactoring procedures behind feature flags; init errors earlier in preinit leaving fewer handlers registered.

Related errors


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