{"record":{"id":"7cdac60fdc83abf7","repo":"clockworklabs/SpacetimeDB","slug":"no-such-procedure","errorCode":"NO_SUCH_PROCEDURE","errorMessage":"ERROR: Invalid procedure ID %u (have %zu procedures)\\n","messagePattern":"ERROR: Invalid procedure ID %u \\(have %zu procedures\\)\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/src/internal/Module.cpp","lineNumber":591,"sourceCode":"    // Call the view handler - returns fully serialized result data, including the header byte.\n    std::vector<uint8_t> result_data = handler_info.handler(ctx, args_source);\n    WriteBytes(result_sink, result_data);\n    \n    return 2;  // Success with data\n}\n\n// Dispatch function for procedures\nint16_t Module::__call_procedure__(\n    uint32_t id,\n    uint64_t sender_0, uint64_t sender_1, uint64_t sender_2, uint64_t sender_3,\n    uint64_t conn_id_0, uint64_t conn_id_1,\n    uint64_t timestamp_microseconds,\n    BytesSource args_source,\n    BytesSink result_sink\n) {\n    // Check if procedure ID is valid\n    if (id >= g_procedure_handlers.size()) {\n        fprintf(stderr, \"ERROR: Invalid procedure ID %u (have %zu procedures)\\n\", \n                id, g_procedure_handlers.size());\n        return -1;  // NO_SUCH_PROCEDURE\n    }\n    \n    // Create sender identity from the 4 uint64_t parts\n    std::array<uint8_t, 32> sender_bytes{};\n    std::memcpy(sender_bytes.data(), &sender_0, 8);\n    std::memcpy(sender_bytes.data() + 8, &sender_1, 8);\n    std::memcpy(sender_bytes.data() + 16, &sender_2, 8);\n    std::memcpy(sender_bytes.data() + 24, &sender_3, 8);\n    \n    Identity sender_identity(sender_bytes);\n    \n    // Create timestamp from microseconds\n    Timestamp timestamp = Timestamp::from_micros_since_epoch(\n        static_cast<int64_t>(timestamp_microseconds));\n    \n    // Create connection ID from the two 64-bit parts (full 128-bit value)","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-cpp/src/internal/Module.cpp#L573-L609","documentation":"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.","triggerScenarios":"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.","commonSituations":"Version skew between module builds; refactoring procedures behind feature flags; init errors earlier in preinit leaving fewer handlers registered.","solutions":["Republish the module so procedure IDs and handlers line up","Keep procedure registration macros unconditional","Verify server logs show a clean module init (no skipped preinit steps)","Regenerate client bindings after procedure schema changes"],"exampleFix":"// before\n#if WITH_PROCEDURES\nPROCEDURE(compute) { /* ... */ }\n#endif\n\n// after\nPROCEDURE(compute) { /* ... */ } // always registered","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register procedures unconditionally across build configurations","Republish and regenerate bindings whenever procedures change","Guard CI with a handler-count smoke test like the reducer one"],"tags":["spacetimedb","cpp","procedure","dispatch","module-version-mismatch"],"backgroundTag":"no-such-procedure","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"}