{"record":{"id":"057d1179324fa430","repo":"clockworklabs/SpacetimeDB","slug":"error-http-handler-must-be-registered-before-it-i","errorCode":null,"errorMessage":"ERROR: HTTP handler must be registered before it is referenced by a router\n","messagePattern":"ERROR: HTTP handler must be registered before it is referenced by a router\n","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/bindings-cpp/src/internal/Module.cpp","lineNumber":132,"sourceCode":"    \n    // Register a procedure handler (called by V9Builder during registration)\n    void RegisterProcedureHandler(const std::string& name,\n                                  std::function<std::vector<uint8_t>(ProcedureContext&, BytesSource)> handler) {\n        g_procedure_handlers.push_back({name, handler});\n    }\n\n    void RegisterHttpHandlerHandler(const std::string& name,\n                                    HttpHandlerSymbol handler_symbol,\n                                    std::function<HttpResponse(HandlerContext&, HttpRequest)> handler) {\n        g_http_handlers.push_back({name, handler_symbol, handler});\n    }\n\n    std::string LookupHttpHandlerName(HttpHandlerSymbol handler_symbol) {\n        auto it = std::find_if(g_http_handlers.begin(), g_http_handlers.end(), [&](const auto& existing) {\n            return existing.symbol == handler_symbol;\n        });\n        if (it == g_http_handlers.end()) {\n            fprintf(stderr, \"ERROR: HTTP handler must be registered before it is referenced by a router\\n\");\n            std::abort();\n        }\n        return it->name;\n    }\n    \n    // Get the number of registered view handlers\n    size_t GetViewHandlerCount() {\n        return g_view_handlers.size();\n    }\n    \n    size_t GetAnonymousViewHandlerCount() {\n        return g_view_anon_handlers.size();\n    }\n    \n    // Get the number of registered procedure handlers\n    size_t GetProcedureHandlerCount() {\n        return g_procedure_handlers.size();\n    }","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-cpp/src/internal/Module.cpp#L114-L150","documentation":"LookupHttpHandlerName() scans g_http_handlers (filled by RegisterHttpHandlerHandler) for the handler symbol a Router route references; when no entry matches it prints this message and calls std::abort() during module preinit. HTTP handler registration must execute before the router that references it, because ordering is driven by the numeric prefixes of the generated __preinit__NN_* export functions.","triggerScenarios":"A route references a handler whose HTTP_HANDLER registration macro expands to a preinit function that runs after the router's preinit; handler and router split across translation units with unfavorable preinit numbering; the handler symbol referenced by the route differs from the one actually registered.","commonSituations":"Moving handler macros into a separate header/file during refactoring so their __preinit__ ordering lands after the router's; hand-writing router registration instead of using the provided macros that guarantee ordering.","solutions":["Move the HTTP handler registration macro so it is registered before the router references it (earlier in the same translation unit, or via a smaller __preinit__ sequence number)","Declare the handler and its registration in the same header that defines the router, so include order enforces registration order","Verify the handler symbol name used by the route exactly matches the registered handler symbol"],"exampleFix":"// before: router preinit runs before handler registration\nROUTER(my_router);        // references get_user handler\nHTTP_HANDLER(get_user);   // registered too late -> abort\n\n// after\nHTTP_HANDLER(get_user);   // register handler first\nROUTER(my_router);        // then reference it","handlingStrategy":"validation","validationCode":"# verify preinit ordering in the built module before publishing\n# nm <module.wasm> | grep __preinit | sort\n# handler registration exports must sort before the router registration export\nnm my_module.wasm | grep '__preinit' | sort","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Define HTTP handlers and their registration macros in the same header the router includes","Place handler registration textually before router construction in every translation unit","Run the nm-based ordering check in CI for modules using the HTTP feature"],"tags":["spacetimedb","cpp","http","router","handler-registration","abort"],"backgroundTag":"handler-not-registered","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}