{"record":{"id":"00866fd6aa6e170a","repo":"clockworklabs/SpacetimeDB","slug":"error-skipping-view-registration-s-because-cir","errorCode":null,"errorMessage":"ERROR: Skipping view registration '%s' because circular reference error is set\n","messagePattern":"ERROR: Skipping view registration '(.+?)' because circular reference error is set\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings-cpp/include/spacetimedb/internal/v10_builder.h","lineNumber":454,"sourceCode":"\n        RawReducerDefV10 reducer_def{\n            reducer_name,\n            ProductType{},\n            FunctionVisibility::Private,\n            MakeUnitAlgebraicType(),\n            MakeStringAlgebraicType(),\n        };\n        UpsertReducer(reducer_def);\n        UpsertLifecycleReducer(RawLifeCycleReducerDefV10{lifecycle, reducer_name});\n    }\n\n    template<typename Func>\n    void RegisterView(const std::string& view_name,\n                      Func func,\n                      bool is_public,\n                      const std::vector<std::string>& param_names = {}) {\n        if (g_circular_ref_error) {\n            std::fprintf(stderr, \"ERROR: Skipping view registration '%s' because circular reference error is set\\n\",\n                        view_name.c_str());\n            return;\n        }\n        (void)param_names;\n        using traits = function_traits<Func>;\n        using ContextType = std::remove_cv_t<std::remove_reference_t<typename traits::template arg_t<0>>>;\n        using ReturnType = typename traits::result_type;\n        static_assert(traits::arity > 0, \"View must have at least one parameter (ViewContext or AnonymousViewContext)\");\n        static_assert(std::is_same_v<ContextType, ViewContext> || std::is_same_v<ContextType, AnonymousViewContext>,\n            \"First parameter of view must be ViewContext or AnonymousViewContext\");\n\n        if constexpr (std::is_same_v<ContextType, ViewContext>) {\n            std::function<std::vector<uint8_t>(ViewContext&, BytesSource)> handler =\n                [func](ViewContext& ctx, BytesSource args_source) -> std::vector<uint8_t> {\n                    (void)args_source;\n                    auto result = func(ctx);\n                    IterBuf buf = IterBuf::take();\n                    bsatn::Writer writer(buf.get());","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-cpp/include/spacetimedb/internal/v10_builder.h#L436-L472","documentation":"RegisterView refuses to register a view because g_circular_ref_error is set — the module's type registration already detected a circular type reference. Views take a ViewContext or AnonymousViewContext first parameter and return rows of some type; when that (or any other) type closed a cycle, the global flag was set and this registration is skipped so the broken module gains no further entries. preinit_99 later fails the whole module, so this is a cascade of the type-cycle error.","triggerScenarios":"The ST_VIEW macro instantiates a static registration calling RegisterView('<view>', fn) whose result/parameter types are, or depend on, a self- or mutually-referential type. Type building runs before view registration during static init, sets the flag, and the view is dropped with this message.","commonSituations":"Adding a view over a table whose row type was just made recursive; combining views with hierarchy-style schemas that embed children by value; bindings upgrades that moved view registration after type building, surfacing pre-existing cycles.","solutions":["Fix the '[CIRCULAR REFERENCE DETECTED]' type named earlier in stderr (use ID members instead of embedded values)","Audit the view's row type and its nested members for self-reference through Vec/Option/struct members","Rebuild; confirm the view appears in the published module","Remember the guard fires for the whole module — one cycle suppresses every view, reducer, and index registration after it"],"exampleFix":"// before — view over recursive row type is skipped\nstruct Item { std::vector<Item> subitems; };\n// after\nstruct Item { std::vector<uint64_t> subitem_ids; };","handlingStrategy":"validation","validationCode":"#include <spacetimedb/internal/module_type_registration.h>\nTEST(Module, ViewsRegistered) {\n    EXPECT_FALSE(SpacetimeDB::Internal::g_circular_ref_error);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep view result types acyclic (IDs over embeddings)","List expected views in a test and compare with the registered module","Remember the guard is module-wide: one cycle drops every view"],"tags":["spacetimedb","cpp","view","circular-reference","schema","static-initialization"],"backgroundTag":"circular-type-reference","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}