clockworklabs/SpacetimeDB · error
ERROR: Invalid http handler ID %u (have %zu handlers)\n
Error message
ERROR: Invalid http handler ID %u (have %zu handlers)\n
What it means
Dispatch guard in Module::__call_http_handler__: the host invoked an HTTP handler by numeric ID >= g_http_handlers.size(). The function logs the message and returns -1, failing the HTTP request. The http-handler table registered at module init is smaller than the IDs the server dispatches, i.e. binary and published module description disagree.
Source
Thrown at crates/bindings-cpp/src/internal/Module.cpp:639
// Call the procedure handler - this may trap if there's an error
std::vector<uint8_t> result_data = handler_info.handler(ctx, args_source);
// If we got here, procedure succeeded - write result
WriteBytes(result_sink, result_data);
return 0; // Success (StatusCode::OK)
}
int16_t Module::__call_http_handler__(
uint32_t id,
uint64_t timestamp_microseconds,
BytesSource request_source,
BytesSource request_body_source,
BytesSink response_sink,
BytesSink response_body_sink
) {
if (id >= g_http_handlers.size()) {
fprintf(stderr, "ERROR: Invalid http handler ID %u (have %zu handlers)\n",
id, g_http_handlers.size());
return -1;
}
Timestamp timestamp = Timestamp::from_micros_since_epoch(static_cast<int64_t>(timestamp_microseconds));
HandlerContext ctx(timestamp);
std::vector<uint8_t> request_bytes = ConsumeBytes(request_source);
bsatn::Reader request_reader(request_bytes.data(), request_bytes.size());
wire::HttpRequest wire_request = bsatn::deserialize<wire::HttpRequest>(request_reader);
HttpRequest request = convert::from_wire(wire_request, ConsumeBytes(request_body_source));
HttpResponse response = g_http_handlers[id].handler(ctx, std::move(request));
auto [wire_response, response_body] = convert::to_wire_split(response);
std::vector<uint8_t> response_metadata;
{
bsatn::Writer writer(response_metadata);View on GitHub (pinned to 6dee26c6ef)
Solutions
- Republish the module so the HTTP handler table matches what the server dispatches
- Register every HTTP handler unconditionally; keep handler macros ahead of router references (see error 663)
- Check server logs for module init errors that could have skipped handler registration
- Retest with a fresh HTTP request after republish - cached routing metadata can also live server-side
Example fix
// before HTTP_HANDLER(get_user); #ifdef ADMIN HTTP_HANDLER(admin_panel); // sometimes absent -> id mismatch #endif // after HTTP_HANDLER(get_user); HTTP_HANDLER(admin_panel); // always registered
Defensive patterns
Strategy: validation
Prevention
- Keep HTTP handler macros unconditional and ordered before router references
- Republish after changing the handler set so server-side routing metadata refreshes
- Smoke-test one request per route after publish
When it happens
Trigger: HTTP handler registration (RegisterHttpHandlerHandler) skipped for some handlers because of conditional compilation or a partially failed preinit; stale module binary served against newer metadata; handler/router macros reordered so fewer handlers register.
Common situations: Iterating on the unstable HTTP feature and republishing while the server caches the previous handler table; feature-flag builds that exclude some handlers.
Related errors
- NO_SUCH_REDUCER
- NO_SUCH_VIEW
- NO_SUCH_PROCEDURE
- Router registration failed: %s
- ERROR: HTTP handler must be registered before it is referenc
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/20283899e7070f5c.
Report an issue: GitHub.