Skip to content

UserIdentityCache holds a NodeTypeDefinition where a User is expected — As<User> fails #2160

Closed

Description

@meshweaver-cloud

What is failing

MeshWeaver.Blazor.Infrastructure.UserIdentityCache.As<User>() observed a cached identity that is not a User at all — it is a MeshWeaver.Graph.Configuration.NodeTypeDefinition (from MeshWeaver.Graph). The cache path took the failure branch and logged at fail: level; the calling circuit almost certainly then saw a null/absent user for that request.

Probable cause

Medium confidence on the diagnosis, low on root cause. The log message itself is unambiguous — the object stored in the user-identity slot is of the wrong type — but the incident does not pin down how it got there. Three shapes are plausible:

  1. A cache-key collision: UserIdentityCache shares storage (or a key namespace) with something that legitimately caches NodeTypeDefinition instances, and a user id collides with a node-type id.
  2. A mis-typed write: some code path calls the cache's setter with a NodeTypeDefinition where it should pass a User — likely via an object/generic overload that skipped a compile-time check.
  3. An identity-provider mis-registration where the "current user" for that circuit resolves to a graph node-type definition rather than a user principal.

The captured "stack" in the sample is not useful — it is a truncated, repeating StreamConfiguration<T>.GetHashCode() / SynchronizationStream<T>.GetHashCode() / ObjectEqualityComparer<T>.GetHashCode() loop with no application frames above it. That is almost certainly a sampler artifact from a hash lookup on the way in to the cache, not the call site that produced the log. Treat topFrame here as noise; the message is the signal.

Impact

Low so far — one occurrence, one pod, one moment. This is a logged failure inside a cache lookup, not an unhandled exception, so the process stays up; the affected circuit just does not get a User back and downstream code sees a null identity. Worth fixing on defect grounds (silently missing identity is a real UX/authorization bug) but not an outage.

Where to look

  • MeshWeaver.Blazor.Infrastructure.UserIdentityCache, specifically the As<TUser>() method that emits this message, and whichever setter / add path populates the user slot. That is the one place that knows what type the value should be and what the key looked like.
  • If the same cache instance (or dictionary) is used to hold anything from MeshWeaver.Graph.Configuration (e.g. NodeTypeDefinition lookups) — check the key scheme for collisions.
  • Log the offending key alongside the value type on that fail: branch so the next occurrence tells us which identity collided, not just the type of the stray object.

Evidence

Fingerprint 6e643370636ed34a
Category MeshWeaver.Blazor.Infrastructure.UserIdentityCache
Severity Error
Top frame MeshWeaver.Data.Serialization.StreamConfiguration1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()`
Namespace memex
Pods memex-portal-deployment-7cfbf545d9-gtlhr
Occurrences 2
First seen 2026-08-24 17:48:16Z
Last seen 2026-08-24 17:48:16Z
Recent log lines
2026-08-24 17:48:16Z memex-portal-deployment-7cfbf545d9-gtlhr fail: MeshWeaver.Blazor.Infrastructure.UserIdentityCache[0]
      As<User> for User: value is MeshWeaver.Graph.Configuration.NodeTypeDefinition (MeshWeaver.Graph), not convertible
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode(System.__Canon)
   at MeshWeaver.Data.Serialization.StreamConfiguration`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at MeshWeaver.Data.Serialization.SynchronizationStream`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode(System.__Canon)
   at MeshWeaver.Data.Serialization.StreamConfiguration`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at MeshWeaver.Data.Serialization.SynchronizationStream`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode(System.__Canon)
   at MeshWeaver.Data.Serialization.StreamConfiguration`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at MeshWeaver.Data.Serialization.SynchronizationStream`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, …[truncated]
2026-08-24 17:48:16Z memex-portal-deployment-7cfbf545d9-gtlhr fail: MeshWeaver.Blazor.Infrastructure.UserIdentityCache[0]
      As<User> for User: value is MeshWeaver.Graph.Configuration.NodeTypeDefinition (MeshWeaver.Graph), not convertible
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode(System.__Canon)
   at MeshWeaver.Data.Serialization.StreamConfiguration`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at MeshWeaver.Data.Serialization.SynchronizationStream`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode(System.__Canon)
   at MeshWeaver.Data.Serialization.StreamConfiguration`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at MeshWeaver.Data.Serialization.SynchronizationStream`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode(System.__Canon)
   at MeshWeaver.Data.Serialization.StreamConfiguration`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at MeshWeaver.Data.Serialization.SynchronizationStream`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetHashCode()
   at System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, …[truncated]

Opened automatically from Admin/_LogIncident/6e643370636ed34a. Recurrences are folded into this issue rather than opening new ones.

Activity

  1. rbuergi commented on Aug 25, 2026

    @rbuergi
    Contributor

    Fixed by #2245 (merged): the User NodeType declaration carried nodeType: User, so the portal's user-directory query (UserIdentityCache, nodeType:User) returned the declaration alongside the real accounts and read its NodeTypeDefinition content as a User on every index emission.

    The colliding key was the declaration's own NodeType field — a declaration filed under the very type it declares is indistinguishable from an instance. Declarations now say NodeType = MeshNode.NodeTypePath, matching Space/Release/Build. Same fix covers VUser and Partition.

    Nothing was ever cached wrongly and nothing re-populated: UserIdentityCache is a DI singleton with one subscription, and TryGetEmail rejects the row each time — the collision lived in the query result, not in the cache's storage, so the row simply reappeared in the next emission. Removing it from the result set makes the line impossible at any emission rate.

    Measured A/B over a full MeshWeaver.Hosting.Monolith.Test assembly run, same host: clean main logs this line 3×, the fix logs it 0×. NodeTypeDeclarationSelfTypingTest ratchets the invariant for every statically-registered declaration, present and future.

    Also kills item D of #2229 (left open — multi-part issue owned elsewhere).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions