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

  1. Republish the module so the HTTP handler table matches what the server dispatches
  2. Register every HTTP handler unconditionally; keep handler macros ahead of router references (see error 663)
  3. Check server logs for module init errors that could have skipped handler registration
  4. 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

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


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