{"record":{"id":"1f1ff3fecf25116f","repo":"clockworklabs/SpacetimeDB","slug":"no-such-reducer","errorCode":"NO_SUCH_REDUCER","errorMessage":"ERROR: Invalid reducer ID %u (have %zu reducers)\\n","messagePattern":"ERROR: Invalid reducer ID %u \\(have %zu reducers\\)\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/src/internal/Module.cpp","lineNumber":474,"sourceCode":"    \n    size_t bytes_to_write = bytes.size();\n    FFI::bytes_sink_write(sink, bytes.data(), &bytes_to_write);\n}\n\nStatus Module::__call_reducer__(\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    Timestamp timestamp,\n    BytesSource args_source,\n    BytesSink error_sink\n) {\n    // Clear any previous error state\n    SpacetimeDB::Internal::clear_reducer_error();\n\n    // Check if reducer ID is valid\n    if (id >= g_reducer_handlers.size()) {\n        fprintf(stderr, \"ERROR: Invalid reducer ID %u (have %zu reducers)\\n\", \n                id, g_reducer_handlers.size());\n        \n        // Write error message\n        std::string error = \"Invalid reducer ID: \" + std::to_string(id);\n        WriteBytes(error_sink, std::vector<uint8_t>(error.begin(), error.end()));\n        return StatusCode::NO_SUCH_REDUCER;\n    }\n    \n    // Create reducer context\n    std::array<uint8_t, 32> sender_bytes{};\n    // Pack the 4 uint64_t parts into 32 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    ","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-cpp/src/internal/Module.cpp#L456-L492","documentation":"Dispatch guard in Module::__call_reducer__: the host invoked a reducer by numeric ID >= the number of reducer handlers registered at module init (g_reducer_handlers). The handler writes 'Invalid reducer ID: <id>' into the caller's error sink and returns StatusCode::NO_SUCH_REDUCER (999), which the client surfaces as a failed reducer call. It means the server's reducer table (captured at publish time) and the binary's registered handlers disagree.","triggerScenarios":"The deployed wasm binary does not match the module description the server dispatches against (partial/failed publish or stale binary); reducer registration macros compiled out or wrapped in runtime conditionals so fewer handlers register; an earlier preinit error aborted part of registration; name-index drift after adding/removing reducers between the client's expectation and the published module.","commonSituations":"Publishing a new module version while old clients/server metadata cache the previous reducer list; #ifdef-ing out a reducer in one build configuration; init failure swallowed before all __preinit__30_* reducer registration functions ran.","solutions":["Republish the module so the server's reducer table matches the binary, then retry the call","Make every reducer registration macro unconditional (no runtime branches around registration) so the handler count is deterministic","Check server logs for preinit/registration errors at module startup that could have skipped handlers","Verify the client calls reducers by the exact registered names and uses freshly generated bindings after schema changes"],"exampleFix":"// before\nREDUCER(create_user) { /* ... */ }\n#ifndef DEBUG\nREDUCER(audit_log) { /* ... */ } // conditionally absent -> id shift\n#endif\n\n// after\nREDUCER(create_user) { /* ... */ }\nREDUCER(audit_log) { /* ... */ } // always registered, stable ids","handlingStrategy":"validation","validationCode":"// post-build test: handler counts must match the expected, published module\n// assert(Module::GetReducerHandlerCount() == EXPECTED_REDUCERS);\n// and assert every expected name is present in __describe_module__ output","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never wrap reducer registration macros in runtime conditionals or #ifdefs that vary by build","Republish the module whenever reducers are added, removed, or reordered; regenerate client bindings","Add a CI test comparing registered handler counts against a golden module description"],"tags":["spacetimedb","cpp","reducer","dispatch","module-version-mismatch"],"backgroundTag":"no-such-reducer","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"}