clockworklabs/SpacetimeDB · critical · InvalidOperationException
Called NonValueChange on a ValueDelta in an ambiguous state:
Error message
Called NonValueChange on a ValueDelta in an ambiguous state: {this} What it means
The client-side cache for MultiDictionary tables accumulates signed multiplicity deltas per key, holding at most two distinct values (D1/D2). NonValueChange requires exactly one of them to have a zero delta; when both are zero or both are non-zero with the same sign, the invariant is broken. The code comment explicitly calls this a server-side error and throws — it is not an application-logic failure.
Source
Thrown at sdks/csharp/src/MultiDictionary.cs:509
else
{
// Now we're in a weird place.
// We're not an update, but D2 is initialized.
// This means that at least one of D1 or D2 has Delta == 0.
// If exactly one of them has Delta == 0, we're okay:
if (D1.Delta == 0 && D2.Value.Delta != 0)
{
return D2.Value;
}
else if (D1.Delta != 0 && D2.Value.Delta == 0)
{
return D1;
}
else
{
// In this case, something strange is going on: both values have the same sign.
// There's nothing sensible to do here, and this represents a server-side error, so just throw.
throw new InvalidOperationException($"Called NonValueChange on a ValueDelta in an ambiguous state: {this}");
}
}
}
}
/// <summary>
/// Add a copy of this Value to this KeyDelta.
/// </summary>
/// <param name="value"></param>
/// <param name="equalityComparer"></param>
public void Add(TValue value, IEqualityComparer<TValue> equalityComparer)
{
if (equalityComparer.Equals(value, D1.Value))
{
D1.Delta += 1;
}
else if (D2 == null)
{View on GitHub (pinned to 524b4487d9)
Solutions
- Update the C# SDK and the SpacetimeDB server to matching released versions
- If you pass a custom IEqualityComparer<TValue> to MultiDictionary, verify it is a proper, stable equality (consistent with value equality the server observes)
- Reconnect and resubscribe to rebuild the client cache from a clean snapshot
- Capture the exception plus the reducer/transaction context and file a SpacetimeDB bug — the source marks this as a server error
Defensive patterns
Strategy: try-catch
Try / catch
// Around the code that drives FrameTick / message processing in non-Unity hosts:
try { conn.FrameTick(); }
catch (InvalidOperationException e) when (e.Message.Contains("ambiguous state"))
{ /* client/server cache desync: disconnect, rebuild the connection, resubscribe */ } Prevention
- Keep SDK and server versions in lockstep; this path indicates a server-side diff bug
- Avoid custom IEqualityComparer implementations that disagree with value equality
- Capture and report the exact transaction that triggers it
When it happens
Trigger: Applying subscription/transaction updates to a table stored in a MultiDictionary when the server diff for one key degenerates into an ambiguous two-value state. Typically coincides with SDK/server version mismatch or a server diff-generation bug; an inconsistent custom IEqualityComparer<TValue> can also collapse distinct values incorrectly.
Common situations: Client cache updates after a long-lived subscription on SDK and server versions that drifted apart; custom equality comparers on the value type; reproduces consistently on the same reducer/transaction.
Related errors
- never types are not yet supported in C# output
- Unsupported --dotnet-version {version}. Supported values: 8,
- --namespace is only supported with --lang csharp
- --dotnet-version is only supported for C# projects (--lang c
- --native-aot is only supported for C# projects (--lang cshar
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/1046082f3c13f2cc.
Report an issue: GitHub.