# Sync Stress Failed Cases ## Recording rule for CLI sync stress failures - Date added: 2026-07-01 - Scope: `scripts/cli-concurrent-edit-stress.mjs`, local `db-sync` server runs, and multi-client CLI sync stress graphs. - Rule: every hard failure or suspicious no-op from the stress harness must get an entry in this file before the issue is considered handled. - Required fields for each entry: graph, command or log path, symptom, root cause, fix, regression test or stress verification, and current status. - Do not mark a case fixed from a retry alone. A fixed case needs a concrete root cause and a post-fix run or targeted test that covers the same path. ## CLI tag-name resolution failed during expanded stress - Date: 2026-07-01 - Graph: `cli-test-5` - Command: `node scripts/cli-concurrent-edit-stress.mjs --graph cli-test-5 --concurrency 3 --sync --offline --offline-ms 800 --timeout-ms 20000 --max-ops 80 --extra-pages 2 --journal-pages 2 --journal-start 2026-07-01` - Symptom: `upsert block --update-tags '["cli-stress-tag-a"]'` failed with `Cannot parse :find, expected: (find-rel | find-coll | find-tuple | find-scalar)`. - Root cause: OCaml CLI tag-name resolution used a duplicated Datascript class query path for tag names. Numeric tag ids worked, but string tag names failed before the outliner mutation was applied. - Regression test: `cli/test/test_cases.ml` now covers `upsert block --update-tags '["Tag A"]'` resolving through `thread-api/cli-list-tags`. - Fix: tag-name resolution in `cli/lib/upsert.ml`, `cli/lib/add.ml`, and `cli/lib/update.ml` now uses the existing tag list endpoint instead of the broken query path. - Sync status after the failed stress smoke: local and remote tx both reached `71`, pending queues were zero, and checksums matched (`b18d36f60f52de7e`). ## CLI sync stress failed cases from multi-client expansion ### Fresh 5000-op stress verification after sync fixes - Date: 2026-07-01 - Graphs: - `cli-sync-stress-assert-20260701-1` - `cli-sync-stress-5000-20260701-13` - `cli-sync-stress-5000-20260701-15` - `cli-sync-stress-5000-20260701-snapshot-last-error-1` - Commands: - Assertion run: `DB_SYNC_CHECKSUM_ASSERT=true LOGSEQ_BIN=/Users/tiensonqin/Codes/projects/logseq/static/logseq-cli.js node scripts/cli-concurrent-edit-stress.mjs --graph cli-sync-stress-assert-20260701-1 --config tmp/cli-sync-stress-assert-20260701-1/cli.edn --root-dir tmp/cli-sync-stress-assert-20260701-1/root --log-file tmp/cli-sync-stress-assert-20260701-1/events.jsonl --clients 3 --concurrency 8 --max-ops 5000 --sync --offline --no-e2ee --timeout-ms 20000 --settle-attempts 60 --settle-ms 1000` - Normal run: `LOGSEQ_BIN=/Users/tiensonqin/Codes/projects/logseq/static/logseq-cli.js node scripts/cli-concurrent-edit-stress.mjs --graph cli-sync-stress-5000-20260701-13 --config tmp/cli-sync-stress-multi-5000-20260701-13/cli.edn --root-dir tmp/cli-sync-stress-multi-5000-20260701-13/root --log-file tmp/cli-sync-stress-multi-5000-20260701-13/events.jsonl --clients 3 --concurrency 8 --max-ops 5000 --sync --offline --no-e2ee --timeout-ms 20000 --settle-attempts 60 --settle-ms 1000` - Reject rollback run: `LOGSEQ_BIN=/Users/tiensonqin/Codes/projects/logseq/static/logseq-cli.js node scripts/cli-concurrent-edit-stress.mjs --graph cli-sync-stress-5000-20260701-15 --config tmp/cli-sync-stress-multi-5000-20260701-15/cli.edn --root-dir tmp/cli-sync-stress-multi-5000-20260701-15/root --log-file tmp/cli-sync-stress-multi-5000-20260701-15/events.jsonl --clients 3 --concurrency 8 --max-ops 5000 --sync --offline --no-e2ee --timeout-ms 20000 --settle-attempts 60 --settle-ms 1000` - Snapshot-last-error run: `LOGSEQ_BIN=/Users/tiensonqin/Codes/projects/logseq/static/logseq-cli.js node scripts/cli-concurrent-edit-stress.mjs --graph cli-sync-stress-5000-20260701-snapshot-last-error-1 --config tmp/cli-sync-stress-snapshot-last-error-5000-1/cli.edn --root-dir tmp/cli-sync-stress-snapshot-last-error-5000-1/root --log-file tmp/cli-sync-stress-snapshot-last-error-5000-1/events.jsonl --clients 3 --concurrency 8 --max-ops 5000 --sync --offline --no-e2ee --timeout-ms 20000 --settle-attempts 60 --settle-ms 1000` - Result: - `cli-sync-stress-assert-20260701-1` completed `5001` started ops, all clients settled at tx `6074`, final recomputed/local/remote checksum was `75663df27432e5c6`, and final `graph validate` passed on all three clients. - `cli-sync-stress-5000-20260701-13` completed `5001` started ops, final recomputed/local/remote checksum was `f3b46db99d7293d1` on all three clients, and final `graph validate` passed on all three clients. - `cli-sync-stress-5000-20260701-15` completed `5001` started ops after the rejected-local-tx rollback fix, final recomputed/local/remote checksum was `7c746bd7fb4ba9b3` on all three clients, and final `graph validate` passed on all three clients. - `cli-sync-stress-5000-20260701-snapshot-last-error-1` completed `5001` started ops after the snapshot-last-error fix and bundle rebuild, final recomputed/local/remote checksum was `5790fdbc975a6b36` on all three clients, and final `graph validate` passed on all three clients. - `cli-sync-stress-5000-20260701-20` completed `5001` started ops after the property-batch stale target fix and bundle rebuild, final recomputed/local/remote checksum was `fc3492f6c370efe4` on all three clients, and final `graph validate` passed on all three clients. - The snapshot-last-error run's event log had no `sync-start-runtime-error`, `pending-tx-snapshot-changed`, `apply-remote-txs-failed`, fatal event, error-level event, checksum mismatch marker, or `prev-checksum-not-match` entry. - The db-sync server log for the normal run had no `:before-checksum-error`, `server checksum doesn't match`, `prev-checksum-not-match`, `last-error`, or exception entries. - Non-fatal anomalies: - `cli-sync-stress-5000-20260701-15` had one recovered `:db-sync/apply-remote-txs-failed` worker log on client 3. The run later converged and validated; the transient failure is tracked in the open recovered remote-apply case below. - `cli-sync-stress-5000-20260701-18` completed `5001` started ops, final recomputed/local/remote checksum `3cce9543989a7855` on all three clients, and final `graph validate` passed on all three clients. It still logged a recovered severe `:db-sync/apply-remote-txs-failed` after exhausting the immediate snapshot-drift retry budget; that is tracked in the delayed snapshot retry case below and this run is not counted as final verification for that later fix. - `cli-sync-stress-5000-20260701-20` had three local `http-set-block-property` operations classified as `race-conflict` because their target blocks were deleted concurrently. Those HTTP handler exceptions are documented below and are not remote apply, checksum, or validation failures. - Status: five fresh 5000-op runs passed after rebuilding `static/db-worker-node.js`; the latest run also verified the property-batch stale target fix at event/final-state and worker-log remote-apply level. ### Fresh 10000-op stress verification after sync fixes - Date: 2026-07-01 - Graph: `cli-sync-stress-10000-20260701-1` - Command: `LOGSEQ_BIN=/Users/tiensonqin/Codes/projects/logseq/static/logseq-cli.js node scripts/cli-concurrent-edit-stress.mjs --graph cli-sync-stress-10000-20260701-1 --config tmp/cli-sync-stress-multi-10000-20260701-1/cli.edn --root-dir tmp/cli-sync-stress-multi-10000-20260701-1/root --log-file tmp/cli-sync-stress-multi-10000-20260701-1/events.jsonl --clients 3 --concurrency 8 --max-ops 10000 --sync --offline --no-e2ee --timeout-ms 20000 --settle-attempts 90 --settle-ms 1000` - Result: - Completed `10001` started ops with 3 clients, offline windows, offline today-journal races, HTTP outliner ops, undo/redo, recycle/delete, and multi-client offline rebase operations. - Final `thread-api/recompute-checksum-diagnostics` returned recomputed/local/remote checksum `6a1402088d63be44` for all three clients. - Final `graph validate` passed on all three clients. - Post-run `sync status` on all three clients reported `last-error nil`, `ws-state "open"`, `local-tx 12134`, `remote-tx 12134`, all pending queues `0`, and local/remote checksum `6a1402088d63be44`. - The db-sync server log had no `:before-checksum-error`, `server checksum doesn't match`, `prev-checksum-not-match`, `last-error`, or exception entries. - Non-fatal anomalies: - `http-delete-restore-page` still returned HTTP 200 with `resultTransit false` four times. This is tracked in the open page-delete no-op case below. - One `tag-delete-recreate` delete phase returned `tag-not-found`. The run still converged and validated. Root cause: the stress harness uses a shared volatile tag name, so another worker can delete the tag before the current worker's delete phase runs. Fix: classify `tag-not-found` during `tag-delete-recreate` delete as an expected race, matching the existing volatile property delete classification. Regression test: `scripts/cli-concurrent-edit-stress.test.mjs` covers this classifier path. - Status: passed. This did not reproduce reverse-local-tx, apply-remote-tx, or checksum divergence failures. ### Final 1000-op smoke verification after classifier update - Date: 2026-07-01 - Graph: `cli-sync-stress-1000-20260701-final` - Command: `LOGSEQ_BIN=/Users/tiensonqin/Codes/projects/logseq/static/logseq-cli.js node scripts/cli-concurrent-edit-stress.mjs --graph cli-sync-stress-1000-20260701-final --config tmp/cli-sync-stress-multi-1000-20260701-final/cli.edn --root-dir tmp/cli-sync-stress-multi-1000-20260701-final/root --log-file tmp/cli-sync-stress-multi-1000-20260701-final/events.jsonl --clients 3 --concurrency 8 --max-ops 1000 --sync --offline --no-e2ee --timeout-ms 20000 --settle-attempts 60 --settle-ms 1000` - Result: - Completed `1001` started ops with 3 clients and offline simulation. - Final recomputed/local/remote checksum was `628f67429199e958` on all three clients. - Final `graph validate` passed on all three clients. - Post-run `sync status` on client 1 reported `last-error nil`, `ws-state "open"`, `local-tx 1087`, `remote-tx 1087`, all pending queues `0`, and local/remote checksum `628f67429199e958`. - Status: passed after the volatile tag delete race classifier update. ### Targeted test verification after final stress updates - Date: 2026-07-01 - Commands and results: - `rtk node --test scripts/cli-concurrent-edit-stress.test.mjs scripts/cli-sync-stress-workflow.test.mjs`: 30 tests, 0 failures. - `rtk bb dev:test -v frontend.worker.db-sync-test/validated-transact-retries-when-live-conn-changes-before-commit-test -v frontend.worker.db-sync-test/prepare-upload-tx-entries-drops-empty-txs-test -v frontend.worker.db-sync-test/apply-remote-txs-reverses-parent-insert-with-existing-child-without-orphaning-test -v frontend.worker.db-sync-test/sync-counts-refreshes-idle-stale-local-checksum-test -v frontend.worker.db-sync-test/apply-remote-txs-rechecks-local-txs-when-local-delete-races-temp-snapshot-test -v frontend.worker.db-sync-test/apply-remote-txs-rechecks-local-txs-when-local-delete-races-temp-commit-test -v frontend.worker.db-sync-test/apply-remote-txs-delays-retry-when-local-txs-keep-changing-test -v frontend.worker.db-sync-test/apply-remote-txs-retries-snapshot-drift-even-if-pending-list-stabilizes-test -v frontend.worker.db-sync-test/apply-remote-txs-local-delete-parent-remote-move-then-delete-parent-test -v frontend.worker.db-sync-test/apply-remote-txs-overlap-out-of-order-parent-delete-then-move-repairs-test`: 10 tests, 48 assertions, 0 failures. - `rtk bb dev:test -v frontend.worker.db-sync-test/temp-conn-batch-preserves-cardinality-one-schema-test -v frontend.worker.db-sync-test/rebase-local-insert-then-save-keeps-cardinality-one-values-test -v frontend.worker.db-sync-test/apply-remote-txs-skips-stale-move-before-later-delete-test -v frontend.worker.db-sync-test/apply-remote-txs-skips-stale-move-to-target-before-later-target-delete-test -v frontend.worker.db-sync-test/apply-remote-txs-with-local-changes-rejects-invalid-final-rebase-test -v frontend.worker.db-sync-test/receive-queue-failure-updates-last-sync-error-test -v frontend.worker.db-sync-test/sync-counts-refreshes-idle-stale-local-checksum-test`: 7 tests, 21 assertions, 0 failures. - `rtk bb dev:test -v frontend.worker.db-sync-test/apply-remote-txs-repairs-missing-block-lookup-ref-test -v frontend.worker.db-sync-test/apply-remote-txs-repairs-missing-block-retract-lookup-ref-test -v frontend.worker.db-sync-test/apply-remote-txs-with-local-changes-repairs-missing-block-lookup-ref-test -v frontend.worker.db-sync-test/apply-remote-txs-with-local-changes-repairs-missing-block-datoms-test`: 4 tests, 16 assertions, 0 failures. - `rtk pnpm --dir deps/db test-v logseq.db-test/batch-transact-with-temp-conn-preserves-cardinality-one-schema-test logseq.db-test/batch-transact-with-temp-conn-preserves-retracts-test`: completed the deps/db suite, 114 tests, 418 assertions, 0 failures. - `rtk pnpm --dir deps/db test-v logseq.db-test/batch-transact-with-temp-conn-before-commit-can-abort-live-commit-test logseq.db-test/batch-transact-with-temp-conn-preserves-cardinality-one-schema-test logseq.db-test/batch-transact-with-temp-conn-preserves-retracts-test logseq.db-test/transact-sync-retries-when-live-conn-changes-before-commit-test`: the targeted assertions printed as passing, but the full deps/db runner later stopped producing output in `gc-kvs-table-test` and was interrupted, so this invocation is not counted as a completed pass. - `rtk bb dev:test -v frontend.worker.pipeline-test/recycle-ops-return-apply-result-test`: 1 test, 4 assertions, 0 failures. - `rtk pnpm --dir cli test`: full CLI parity suite passed. - Status: completed commands passed; the latest deps/db retry was interrupted after target assertions printed as passing and is not counted as a completed pass. ### Latest PR 12842 verification - Date: 2026-07-01 - Commands and results: - `rtk pnpm cljs:run-test -n frontend.worker.db-sync-test -e fix-me`: 206 tests, 750 assertions, 0 failures. - `rtk clojure -M:clj-kondo --parallel --lint src/main/frontend/worker/sync/apply_txs.cljs src/test/frontend/worker/db_sync_test.cljs`: 0 errors, 0 warnings. - `rtk node --test scripts/cli-concurrent-edit-stress.test.mjs scripts/cli-sync-stress-workflow.test.mjs`: 32 tests, 0 failures. - `rtk bb dev:lint-and-test`: 1090 tests, 4730 assertions, 0 failures, with lint and translation checks passing. - CLI stress verification: - `cli-sync-stress-10000-20260701-6` completed `10001` started ops with 3 clients, offline windows, offline today-journal races, HTTP outliner ops, undo/redo, recycle/delete, and multi-client offline rebase operations. Final recomputed/local/remote checksum was `43da786afaaf37a8` on all three clients, and final `graph validate` passed on all three clients. - `cli-sync-stress-1000-20260701-230737` completed `1001` started ops with 3 clients and offline simulation. Final recomputed/local/remote checksum was `dc4de34b2c9d2d8d` on all three clients, final `graph validate` passed on all three clients, and the event log had no hard `error`, `fatal`, `failed`, or `no-op` entries. Expected stale-id races were classified as `race-conflict`. - Status: passed. ### Duplicate local and remote `create-page` rebase could remove remote children - Date: 2026-07-01 - Graph: reproduced by worker tests while investigating multi-client offline today-page creation. - Symptom: when one client had a pending local `create-page` and remote txs contained the same page plus new child blocks, rebasing the local `create-page` could treat the page as absent or create a duplicate path instead of preserving the remote page entity and its children. - Root cause: `rebase-local-op!` only looked up an existing page by the local page UUID from the outliner op options. If the same title had already arrived from remote, the rebase path could miss it and run `outliner-page/create!` again instead of turning the local create into an idempotent page resolution. - Fix: `:create-page` rebase now resolves an existing active page by UUID first and then by title. If it finds one, it returns the existing page title and UUID instead of creating another page. - Regression tests: - `frontend.worker.db-sync-test/rebase-create-page-keeps-page-uuid-test` - `frontend.worker.db-sync-test/rebase-duplicate-create-page-keeps-remote-children-test` - `frontend.worker.db-sync-test/apply-remote-txs-rebases-create-delete-page-as-recycled-test` - Status: fixed and covered by the latest 1000-op and 10000-op multi-client offline stress runs. ### Remote recreate in the same batch was misclassified as a missing block repair - Date: 2026-07-01 - Graph: reproduced by worker test from a local-delete and remote-recreate race. - Symptom: if remote txs deleted a block and recreated the same `:block/uuid` in the same batch while the client had a local delete pending, the apply path could ask server repair for that UUID as if it were missing before applying the remote recreate tx. - Root cause: missing-block preflight looked for absent lookup refs in the current DB and after local reversal, but it did not exclude block UUIDs that the incoming remote batch itself creates. Vector tx data was handled, but Datascript Datom tx data from remote apply was not part of the temp-id to UUID extraction path. - Fix: remote apply now extracts created block UUIDs from both vector tx items and Datascript Datoms, subtracts UUIDs that are also retracted in the same batch, and excludes those remote-created UUIDs from missing-block repair preflight. - Regression test: `frontend.worker.db-sync-test/apply-remote-tx-local-delete-remote-recreate-does-not-leave-local-only-delete-test`. - Status: fixed and covered by latest stress verification. ### Delayed snapshot retry returned an inconsistently awaitable result - Date: 2026-07-01 - Graph: reproduced by `frontend.worker.db-sync-test` full namespace run after adding snapshot-drift retry tests. - Symptom: full namespace execution could see a delayed remote-apply retry continue after fixture cleanup, producing `missing-db` from `apply-remote-txs!`. Focused tests were easier to pass because the async cleanup race was narrower. - Root cause: the snapshot-drift retry path returned nested or mixed native/Promesa promise values. The delayed retry branch could be observed as complete before the recursive retry finished, so callers and tests could clean up the repo connection while retry work was still scheduled. - Fix: retry construction now uses one explicit Promesa chain via `