Skip to content

Fix StateVector clocks being read from the client id buffer - #128

Merged
SebastianStehle merged 2 commits into
y-crdt:mainfrom
jcannon98188:fix/state-vector-clocks
Oct 12, 2026
Merged

SebastianStehle merged 2 commits into
y-crdt:mainfrom
jcannon98188:fix/state-vector-clocks

Conversation

@jcannon98188

@jcannon98188 jcannon98188 commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes StateVector returning the client ids as its clock values.

Fixes #127

Problem

StateVectorNative.Clocks() read its values from ClientIdsHandle instead of ClocksHandle, so every StateVector built from native data reported each client's id (truncated to uint) as its clock.

var doc = new Doc(new DocOptions { Id = 1001 });
var text = doc.Text("t");

StateVector? after = null;
using var subscription = doc.ObserveAfterTransaction(e => after = e.AfterState);

using (var transaction = doc.WriteTransaction())
{
    text.Insert(transaction, index: 0, "Brazil"); // 6 characters
}
Result
Expected client=1001 clock=6
Before this change client=1001 clock=1001

This affects AfterTransactionEvent.BeforeState and AfterState, and any other API that returns a StateVector built from native data.

Changes

  • StateVectorNative.Clocks() reads from ClocksHandle. This is a one-line change.

Tests

New StateVectorTests, which fail without the fix and pass with it:

  • ReportsClocksForSingleClient: one doc over two transactions. Expects {} -> {1001: 6} and then {1001: 6} -> {1001: 12}.
  • ReportsDistinctClocksForMultipleClients: a doc merging an update from another client. Expects {2002: 6, 3003: 2}, which checks that each client gets its own clock.

Client ids are set explicitly on every doc in the tests, so the results are deterministic.

Failure output without the fix:

Failed ReportsClocksForSingleClient
  Assert.That(states[0].After.State, Is.EqualTo(new Dictionary<ulong, uint> { [doc.Id] = 6 }))
Failed ReportsDistinctClocksForMultipleClients
  Assert.That(after!.State, Is.EqualTo(new Dictionary<ulong, uint> { [sender.Id] = 6, [receiver.Id] = 2 }))

Notes

  • This is a bug fix with no API change. Code that relied on the wrong values was already getting incorrect results.
  • I ran the two new tests against a yrs.dll built from yrs 0.19.1. I did not run the rest of the unit suite on this branch.

🤖 Generated with Claude Code

@jcannon98188 jcannon98188 changed the title Fix/state vector clocks Fix StateVector clocks being read from the client id buffer Oct 8, 2026
@jcannon98188

Copy link
Copy Markdown
Contributor Author

The tests failing on this are really flaky, and the test failure doesn't have anything to do with the changes. #140 should fix it.

jcannon98188 and others added 2 commits October 11, 2026 12:32
StateVectorNative.Clocks() read from ClientIdsHandle instead of
ClocksHandle, returning wrong clock values.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Covers a single client across two transactions and a document holding
clocks from two distinct clients. Both fail without the Clocks() fix.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@jcannon98188
jcannon98188 force-pushed the fix/state-vector-clocks branch from f922397 to aec073a Compare October 11, 2026 16:32
@SebastianStehle
SebastianStehle merged commit 1e3c31f into y-crdt:main Oct 12, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

StateVector returns the client ids as clock values

2 participants