logseq / logseq/db-test

DB: updating a :default property value orphans the previous value block (invisible in UI, accumulates per edit)

Open
#1,073 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

Summary

In a DB graph, updating a :default-typed property value creates a new value block and leaves the previous one behind as a child of the owning block, referenced by nothing. Each subsequent edit adds another. The abandoned blocks are not rendered in the UI (property rows only show the current value), so they accumulate invisibly — one dead entity per property edit, indefinitely.

Verified through the CLI. I have not confirmed whether the desktop UI's property editor takes the same path — that's the main open question below, and it decides whether this is a CLI issue or a core one.

Repro (CLI)
# fresh property + class + instance
logseq upsert property --name repro-note --type default --cardinality one
logseq upsert tag --name repro-thing --add-properties repro-note
logseq upsert block --target-page "Repro Page" --content "subject block"
logseq upsert block --id <block> --update-tags repro-thing

# three edits to the same property
logseq upsert block --id <block> --update-properties '{:user.property/repro-note-XXXX "first value"}'
logseq upsert block --id <block> --update-properties '{:user.property/repro-note-XXXX "second value"}'
logseq upsert block --id <block> --update-properties '{:user.property/repro-note-XXXX "third value"}'

Each write returns a different value-block db/id (8192, 8193, 8194).

Actual
;; children of the owning block
[:find ?c ?t :where [?c :block/parent 8191] [?c :block/title ?t]]
=> [[8192 "first value"] [8193 "second value"] [8194 "third value"]]

;; what the property actually points at
[:find ?v ?t :where [8191 :user.property/repro-note-XXXX ?v] [?v :block/title ?t]]
=> [[8194 "third value"]]

Three children, one referenced. logseq/logseq#8192 and logseq/logseq#8193 are unreachable from any property, and don't appear anywhere in the UI.

Expected

Either the value block is mutated in place, or the abandoned one is reclaimed with the property that stopped pointing at it. A block that no property references and that the UI never renders shouldn't persist in the tree.

Also observed: property deletion

Same shape, larger blast radius. In a real graph, deleting a :default-typed property that 26 instances had values for left 26 orphaned value blocks in place — the property was gone, its value blocks were not. Combined with a second retired property, 30 unreferenced blocks across one container, none visible in the UI.

Why it's hard to notice

The UI renders property values as property rows — "this property → its current value". A value block that no property points at has no row to render in, so it is simply never drawn. The only way to find these is a DataScript query against :block/parent. A user editing normally has no signal that anything is accruing.

Open question / scope

My repro drives the CLI (logseq upsert block --update-properties). I have not verified whether the desktop UI's property editor mutates the existing value block or mints a new one. If the UI mutates in place, this is scoped to the CLI's upsert path rather than to the DB layer. Happy to test that if it's useful — I just don't want to overstate what I've actually confirmed.

Environment
  • Logseq CLI — Build time 2026-07-28T15:18:36.673Z, Revision 9a11243
  • DB graph (not file-based)
  • macOS 26.5.2
Suggested query for anyone auditing an existing graph

Unreferenced value blocks under instances of a class, given that class's :default property idents:

[:find ?child ?title
 :where
 [?inst :block/tags ?tag] [?tag :db/ident :user.class/YOUR-CLASS]
 [?child :block/parent ?inst] [?child :block/title ?title]
 (not [?inst :user.property/SOME-DEFAULT-PROP ?child])
 (not [?inst :user.property/ANOTHER-DEFAULT-PROP ?child])]

Node-typed properties don't produce these — they point at existing entities, never at child value blocks — so only :default/:number-style properties need listing in the not clauses.

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 by running the CLI repro with logseq upsert block --update-properties and inspect the DataScript queries for child blocks and property references. Compare the CLI path with the desktop UI property editor, which the report has not verified. Done means repeated updates or property deletion no longer leave unreferenced value blocks under the owning block.

Written by the indexing model from the issue text.

Assessment

Tech stack
clojure
Domain
cli, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.