logseq / logseq/db-test

Worker exits at startup (graph unopenable) when a :block/uuid index entry has no entity

Open
#1,214 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
28
Forks
2
PR merge metrics
No merged PRs in 30d

Description

Search first
  • I searched and no similar issues were found
What Happened?

One of my DB graphs can no longer be opened at all on recent builds. The worker exits during startup and the graph is unreachable from both the app and the CLI:

Error (server-start-failed): Worker exited before becoming ready; startup cleanup failed:
Worker close failed: Cannot store nil as a value at {:db/id nil, :block/tx-id 536885855}

The same graph opens normally on an older build (b09316a), so nothing about the graph's contents is unreadable in itself.

The cause is ensure-canonical-revisions!, which runs at startup and walks the :block/uuid AVET index, writing :block/tx-id to each entity. This graph has 3 index entries with no entity behind them (out of 1,215). For those, (d/entity db e) is nil, so the code writes {:db/id nil …} and the transaction throws. One stale index entry makes the whole graph unopenable.

Read-only counts from a copy of db.sqlite:

Count
:block/uuid datoms in the AVET index 1,215
entities actually reachable ([:find (count ?e) :where [?e :block/uuid]], older build) 1,212
index entries whose d/entity is nil 3

Each of the three has no rows in any other index: (d/datoms db :eavt e) is empty and (d/datoms db :aevt :block/uuid e) is 0. So they exist only in the AVET index.

How the graph ended up with stale index entries, I don't know — this report is about startup being fatal because of them.

Reproduce the Bug

I can't offer a from-scratch reproduction, since I don't know how the stale entries were created. On a graph that has one:

  1. Open the graph with a build that includes fb1047d1f8 (e.g. 6bf8fe772f), from the app or via logseq graph info --graph <graph>.
  2. The worker exits during startup and the graph can't be opened. The message above appears in ~/logseq/graphs/<graph>/db-worker-node-<date>.log, after {:db-worker/on-become-master-start …}.
  3. Open the same graph with a build from before that commit (e.g. b09316a): it opens normally.

To check whether a graph has such entries, on a build that can still open it:

;; datoms in the index vs entities that actually exist
(count (d/datoms db :avet :block/uuid))
(count (filter #(nil? (d/entity db (:e %))) (d/datoms db :avet :block/uuid)))
Expected Behavior

A stale index entry shouldn't make a graph unopenable. ensure-canonical-revisions! could skip datoms whose entity is missing (or use (:e datom) instead of (:db/id entity)), and ideally report or clean up the stale entries rather than failing startup.

Screenshots
Browser, Desktop or Mobile Platform Information

macOS 26.6.2 (25G83), arm64. Desktop app 2.0.1 — local build of 6bf8fe772f (built 2026-09-16), CLI logseq --versionRevision: 6bf8fe7-dirty. Working build for comparison: b09316a. Affected graph: DB graph, schema-version {:major 65 :minor 33}, created about a year ago, local (no RTC graph uuid).

Additional Context

Investigation (at 6bf8fe772f; the same code is on current master)

  • Where: src/main/frontend/worker/db_core.cljs:714-724ensure-canonical-revisions!:
    (keep (fn [datom]
            (let [entity (d/entity db (:e datom))]
              (when-not (nat-int? (:block/tx-id entity))
                {:db/id (:db/id entity) :block/tx-id tx-id})))
          (d/datoms db :avet :block/uuid))
    
    (:db/id entity) is nil when the entity is missing, and the resulting map is transacted.
  • Introduced in fb1047d1f8 ("refactor: data fetch && reactivity", 2026-07-20), which is not in b09316a — matching the observation that the older build opens the graph.
  • Why it fails (confirmed): a read-only probe over a copy of the graph found 3 AVET entries with no entity, and the tx-id in the error is consistent with the (inc (:max-tx db)) this function uses (my copy of the graph reports 536885853, the errors showed …854 and …855 on successive attempts).
  • Error reporting differs by build (confirmed): f7362f0-dirty surfaced only server-start-timeout-orphan with the real cause in the worker log; 6bf8fe772f surfaces the message directly. The latter is much easier to diagnose.
  • 43 real entities in this graph legitimately lack :block/tx-id and would be backfilled fine; only the 3 phantom index entries break it (a probe counting through the index sees 46, i.e. 43 + 3).
Are you willing to submit a PR? If you know how to fix the bug.

Not planning to, but happy to test a fix or run further read-only probes on the affected graph.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at src/main/frontend/worker/db_core.cljs:714-724, in ensure-canonical-revisions!, and inspect how :block/uuid AVET datoms are converted to entities before the startup transaction. Reproduce with the affected graph or the provided read-only datom/entity counts; done means graphs containing missing entities no longer fail during startup while real entities still receive canonical revisions.

Written by the indexing model from the issue text.

Assessment

Tech stack
clojure, sqlite
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.