Skip to content

Error: View node is being updated before it is initialized #393

@lazakrisz

Description

@lazakrisz

Hi!

Thanks for this project, it is revolutionary! I'm trying to understand it a bit more and have been playing with it, this is an error that I get quite often, and have been trying to track it down or find the cause of it, with not much success unfortunately 😅.

Error: View node is being updated before it is initialized

Here is the full log from the triplit server:

23:26:21 ⬅ CHANGES_ACK 
23:26:21 ⚠️  ERROR: Error while processing message CHANGES
 Error: View node is being updated before it is initialized
    at IVM.updateViews (file:///Users/krisztianlazar/github/triplit-issue/node_modules/@triplit/cli/dist/chunk-RKJJMDSJ.js:6325:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
23:26:21 ⬅ ERROR CHANGES TriplitError: Triplit Error | Context: An unknown error occurred while processing your request.
23:26:22 ➡ CHANGES 
23:26:22 ⬅ CHANGES_ACK 
23:26:22 ⚠️  ERROR: Error while processing message CHANGES
 Error: View node is being updated before it is initialized
    at IVM.updateViews (file:///Users/krisztianlazar/github/triplit-issue/node_modules/@triplit/cli/dist/chunk-RKJJMDSJ.js:6325:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
23:26:22 ⬅ ERROR CHANGES TriplitError: Triplit Error | Context: An unknown error occurred while processing your request.
23:26:22 ➡ CHANGES 
23:26:22 ⬅ CHANGES_ACK 
23:26:22 ⚠️  ERROR: Error while processing message CHANGES
 Error: View node is being updated before it is initialized
    at IVM.updateViews (file:///Users/krisztianlazar/github/triplit-issue/node_modules/@triplit/cli/dist/chunk-RKJJMDSJ.js:6325:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
23:26:22 ⬅ ERROR CHANGES TriplitError: Triplit Error | Context: An unknown error occurred while processing your request.
23:26:22 ➡ CHANGES 
23:26:22 ⬅ CHANGES_ACK 
23:26:22 ⚠️  ERROR: Error while processing message CHANGES
 Error: View node is being updated before it is initialized
    at IVM.updateViews (file:///Users/krisztianlazar/github/triplit-issue/node_modules/@triplit/cli/dist/chunk-RKJJMDSJ.js:6325:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
23:26:22 ⬅ ERROR CHANGES TriplitError: Triplit Error | Context: An unknown error occurred while processing your request.

here is one of the CHANGES payload:

{
    "type": "CHANGES",
    "payload": {
        "changes": {
            "json": {
                "metas": {
                    "sets": [
                        [
                            "oGdRrCGahVRjyz1QQlIOb",
                            {
                                "id": "oGdRrCGahVRjyz1QQlIOb",
                                "visibility": "private",
                                "userId": "Bn3XcKjbnhrzgdLPQopkdcvuCPHCJ8bJ"
                            }
                        ]
                    ],
                    "deletes": []
                },
                "todos": {
                    "sets": [
                        [
                            "5IQh6-ZtoIXddreyP46IG",
                            {
                                "id": "5IQh6-ZtoIXddreyP46IG",
                                "userId": "Bn3XcKjbnhrzgdLPQopkdcvuCPHCJ8bJ",
                                "text": "This is a dummy todo",
                                "completed": false,
                                "createdAt": "2025-08-14T21:26:22.394Z",
                                "updatedAt": "2025-08-14T21:26:22.394Z",
                                "metaId": "oGdRrCGahVRjyz1QQlIOb"
                            }
                        ]
                    ],
                    "deletes": []
                }
            },
            "meta": {
                "values": {
                    "metas.sets": [
                        "map"
                    ],
                    "metas.deletes": [
                        "set"
                    ],
                    "todos.sets": [
                        "map"
                    ],
                    "todos.deletes": [
                        "set"
                    ]
                }
            }
        }
    }
}

I have found the following Discord conversation: https://discord.com/channels/1138467878623006720/1375318110567137332, where davey had the exact same issues that I'm running into.
Although the Discord thread does pose a solution to this issue, I'm having a hard time understanding what's actually happening, or what is the root cause of the issue.

Suppose I have the following schema:

import { or, Schema as S } from "@triplit/client";
import { authSchema } from "./auth-schema";

const isUid = ["userId", "=", "$token.sub"] as const;

/**
 * Define your schema here. After:
 * - Pass your schema to your Triplit client
 * - Push your schema to your Triplit server with 'triplit schema push'
 *
 * For more information about schemas, see the docs: https://www.triplit.dev/docs/schemas
 */
export const schema = S.Collections({
  ...authSchema,
  // this is just some dummy stuff, can be any other arbitrary type.
  metas: {
    schema: S.Schema({
      id: S.Id(),
      visibility: S.String({ enum: ["public", "private"], default: "private" }),
      userId: S.String(),
    }),
    relationships: {
      todos: S.RelationMany("todos", { where: [["metaId", "=", "$id"]] }),
    },
    permissions: {
      authenticated: {
        read: {
          filter: [["userId", "=", "$token.sub"]],
        },
        insert: {
          filter: [["userId", "=", "$token.sub"]],
        },
        update: {
          filter: [["userId", "=", "$token.sub"]],
        },
        delete: {
          filter: [["userId", "=", "$token.sub"]],
        },
      },
    },
  },
  todos: {
    schema: S.Schema({
      id: S.Id(),
      userId: S.String(),
      text: S.String(),
      completed: S.Boolean({ default: false }),
      createdAt: S.Date({ default: S.Default.now() }),
      updatedAt: S.Date({ default: S.Default.now() }),
      metaId: S.String(),
    }),
    relationships: {
      meta: S.RelationById("metas", "metaId"),
    },
    permissions: {
      authenticated: {
        read: {
          filter: [
            or([
              isUid,
            //   ["meta.visibility", "=", "public"], // this is causing the issue
            ]),
          ],
        },
        insert: {
          filter: [isUid],
        },
        update: {
          filter: [isUid],
        },
        postUpdate: {
          filter: [
            isUid,
            ["updatedAt", ">", "$prev.updatedAt"],
            ["createdAt", "=", "$prev.createdAt"],
          ],
        },
        delete: {
          filter: [isUid],
        },
      },
    },
  },
});

I have tracked the issue down to this particular line:

["meta.visibility", "=", "public"]

I also have the following dummy component that I've used for testing and trying to figure out the root cause of the issue:

"use client";

import { Button } from "@/components/ui/button";
import { triplit } from "@/triplit/client";
import { schema } from "@/triplit/schema";
import { Entity } from "@triplit/client";
import { useQuery } from "@triplit/react";

type TodoType = Entity<typeof schema, "todos">;

export default function Home() {
  const { results: todos } = useQuery(triplit, triplit.query("todos"));

  async function createTodo() {
    const todo = await triplit.transact(async (tx) => {
      const dummy = await tx.insert("metas", {
        userId: triplit.vars.$token.sub,
      });
      const todo = await tx.insert("todos", {
        completed: false,
        metaId: dummy.id,
        text: "This is a dummy todo",
        userId: triplit.vars.$token.sub,
      });

      return todo;
    });
  }

  async function deleteTodos() {
    await triplit.transact(async (tx) => {
      const metas = await tx.fetch(triplit.query("metas").Include("todos"));

      for (const meta of metas) {
        for (const todo of meta.todos) {
          await tx.delete("todos", todo.id);
        }
        await tx.delete("metas", meta.id);
      }
    });
  }

  return (
    <div>
      <div className="flex gap-2">
        <Button type="button" onClick={createTodo}>
          Create Todo
        </Button>
        <Button variant="destructive" type="button" onClick={deleteTodos}>
          Dummy Button
        </Button>
      </div>

      <ul className="mt-4 space-y-2">
        {todos?.map((t) => (
          <li key={t.id} className="flex items-center gap-2">
            <span>{t.text}</span>
            {t.completed && <span className="text-green-600">(Completed)</span>}
          </li>
        ))}
      </ul>
    </div>
  );
}

In the Discord thread it is said that:

Which is that the permission on `applications` for an authenticated user references `organization.members.userId` but neither organizations nor members actually allows anyone but the service token to read them, which is leading to a query that our subscription system is having trouble setting up a graph for

however if I'm not mistaken, in this case meta (my dummy entity) has all the necessary permissions, so does todos entity. Upon further investigating I thought maybe if I change the order of the insert or delete, ex.: insert the todo, and after that insert the meta, and vice versa for the delete. This unfortunately resulting in the issue again.

Here are my questions:

  1. Is there something I'm missing?
  2. How are these entities resolved?
  3. Should this be mentioned in the docs?
  4. What should be the order of these types of mutations when there might be a dependency between the entities being mutated?
  5. Is this caused by some kind of circular dependency, since both entities are referencing each other? 🤔

here is the full repro repo: https://github.com/lazakrisz/triplit-issue
main files are: https://github.com/lazakrisz/triplit-issue/blob/aa9d77a96d6236c4626fd0edbd1eae1ea8778c37/src/triplit/schema.ts#L13
https://github.com/lazakrisz/triplit-issue/blob/aa9d77a96d6236c4626fd0edbd1eae1ea8778c37/src/app/page.tsx#L11

thanks so much! 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions