Skip to content

A CreateNodeRequest addressed to the sending hub itself is never answered (nodeops, empty queue, RunLevel=Started) — activity tracking and every downstream read then time out #1174

Description

@meshweaver-cloud

What is failing

The MeshWeaver.Graph.ActivityTracking service failed to track user activity because the underlying mesh hub for the _UserActivity node never delivered its initial state within the 30-second timeout.

Probable cause

Two occurrences hit the same user (rbuergi) on different paths (Underwriting and rbuergi) in a 1-second window on a single pod, then stopped entirely. The exception message lists four likely causes:

  1. RLS silently rejected the prior CreateNode call
  2. The node path is misspelled or points at a namespace no NodeType claims
  3. The node was deleted between create and update
  4. The per-node hub activated but its MeshDataSource didn't load the node from persistence

The pattern (2 bursts, same user, same pod, no recurrence) most strongly suggests cause (1) — the user rbuergi may lack permission to create _UserActivity nodes under their path — or a transient storage hiccup (cause 4).

Confidence: Low–medium — the evidence is thin and the root cause could be any of the four listed possibilities.

Impact

Very low. Two activity-tracking updates silently failed for one user on one pod within a single second, with no recurrence in the hours since. No customer-facing feature is blocked; activity history for those two paths/events was simply not recorded.

Where to look

  • Component: MeshWeaver.Graph.ActivityTracking — specifically the code path that creates or updates a _UserActivity node and awaits its hub initialization.
  • Check: Whether the _UserActivity node type is registered in the mesh and claims the rbuergi/ path namespace.
  • Check: RLS rules applied to the memex-cloud namespace — does the activity-tracking service identity (or rbuergi themselves) have permission to create nodes under rbuergi/_UserActivity/?
  • Check: The 30-second hub-initialization timeout value and whether the persistence layer (MeshDataSource) was experiencing latency at the time.

Evidence

Fingerprint 7473a637daf1e169
Category MeshWeaver.Graph.ActivityTracking
Severity Error
Exception System.TimeoutException
Namespace memex-cloud
Pods memex-portal-deployment-6bd9c46f8b-z9t6r
Occurrences 7
First seen 2026-08-10 13:49:50Z
Last seen 2026-08-10 14:20:27Z
Recent log lines
2026-08-10 13:49:50Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=rbuergi path=Underwriting
      System.TimeoutException: Update aborted: no initial state arrived for 'rbuergi/_UserActivity/Underwriting' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
2026-08-10 13:49:51Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=rbuergi path=rbuergi
      System.TimeoutException: Update aborted: no initial state arrived for 'rbuergi/_UserActivity/rbuergi' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
2026-08-10 14:03:24Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=carson path=carson
      System.TimeoutException: Update aborted: no initial state arrived for 'carson/_UserActivity/carson' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
2026-08-10 14:13:59Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=rsalzmann path=rsalzmann/DataModeling/Formatting/Exercise
      System.TimeoutException: Update aborted: no initial state arrived for 'rsalzmann/_UserActivity/rsalzmann_DataModeling_Formatting_Exercise' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
2026-08-10 14:15:21Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=rsalzmann path=rsalzmann/DataModeling/Formatting/Exercise/FormatTheMoney
      System.TimeoutException: Update aborted: no initial state arrived for 'rsalzmann/_UserActivity/rsalzmann_DataModeling_Formatting_Exercise_FormatTheMoney' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
2026-08-10 14:16:56Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=rsalzmann path=rsalzmann/DataModeling/Formatting/Exercise/FormatTheMoney
      System.TimeoutException: Update aborted: no initial state arrived for 'rsalzmann/_UserActivity/rsalzmann_DataModeling_Formatting_Exercise_FormatTheMoney' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
2026-08-10 14:20:27Z memex-portal-deployment-6bd9c46f8b-z9t6r fail: MeshWeaver.Graph.ActivityTracking[0]
      Failed to track activity for user=rsalzmann path=ThreeBody
      System.TimeoutException: Update aborted: no initial state arrived for 'rsalzmann/_UserActivity/ThreeBody' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.

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

Activity

  1. rbuergi commented on Aug 10, 2026

    @rbuergi
    Contributor

    Triage verdict: not a defect in MeshWeaver.Graph.ActivityTracking, and none of the four suspected causes in the exception text. This is a prod manifestation of the deploy-roll / NodeType-bake starvation family (#1172, PR #1161, PR #1168, PR #1173), pinned by the roll timeline.

    Evidence (all times 2026-08-10 UTC, namespace memex-cloud, gathered read-only via az aks command invoke):

    1. The portal rolled seven times that day (portal ReplicaSet creations): 07:09:41, 11:44:38, 12:55:24, 12:55:37, 13:38:56, 16:28:07, 19:28:30 — the pre-PR-Portals roll once a day — every roll pays a full NodeType rebuild #1173 self-update cadence (20-min ACR poll, ~44 CI images/day). The erroring pod memex-portal-deployment-6bd9c46f8b-z9t6r booted with the 11:44:38 RS.
    2. The 13:38:56 roll's pod (memex-portal-deployment-59479dc7d9-kmwvr) joined the Orleans cluster at ~13:39 but became Ready only at 15:59:37 (Ready.lastTransitionTime on the still-running pod) — 2 h 20 min held Unhealthy by the nodetype_bake startup gate while it reran the full dynamic-NodeType rebuild (every roll invalidates the whole compile cache — PR Portals roll once a day — every roll pays a full NodeType rebuild #1173's own rationale).
    3. Every one of the 7 occurrences (13:49:50 → 14:20:27) lies inside that 13:38:56 → 15:59:37 join-to-Ready window. Three unrelated users (rbuergi, carson, rsalzmann), five distinct paths — zero occurrences before or after. Orleans places grain activations by membership, not k8s readiness, so per-node-hub activations land on the joining, mid-bake silo and starve behind the compile sweep: RoutingGrain route dispatches hang at 64 in-flight when _Activity compilation stalls #1172 records route dispatch slots exhausting behind non-terminating _Activity/compile dispatches on every freshly booted silo (z9t6r itself at 11:45:09, …67464cbcfc-jlmpw at 12:56:14 — each within ~a minute of its own join), and the enrichment slow path additionally waits on stale NodeTypes queued behind the sweep. The caller's 30 s initial-state bound in UpdateRemote then loses deterministically — producing exactly this signature. The identical boot-window signature is dissected in PR The boot plugin install no longer races the NodeType bake it depends on #1161 (boot install racing the bake) and PR A parked NodeType no longer makes every instance of it un-writable #1168 (parked type burning a 60 s budget against the caller's 30 s).
    4. Reconfirmed live tonight: the 19:28:30 roll's pod memex-portal-deployment-748bfcc86b-2m6vg had been Running/not-Ready for 80+ min at 20:45Z with Health check nodetype_bake … Unhealthy ('NodeType bake in progress'), DynamicTypePreWarmer: Ifrs17/PartnerRating → TimedOut, and 16 [ROUTE] 64 route dispatches are in flight … latest target …/_Activity/compile-… crit lines in its recent log — the same state kmwvr was in during this issue's window.

    Falsifying the exception's own suspects: (1) RLS — these same users' tracking succeeds at every other time of day; an RLS denial is time-invariant, this failure is strictly roll-correlated. (2)/(3) typo'd path / deleted node — three unrelated users, five paths, failing only inside one roll window. (4) is the closest but one level down: the per-node hub never finished activating on the starved silo (same conclusion PR #1161 reached for the boot-install victim of this state).

    Resolution:

  2. rbuergi commented on Aug 10, 2026

    @rbuergi
    Contributor

    Closing as duplicate of #1172 — same starvation, different victim.

    Decisive evidence (read-only cluster forensics, full detail in the comment above): every occurrence of this signature (13:49:50–14:20:27Z, three unrelated users) lies inside the 13:38:56 roll's join-to-Ready window — pod kmwvr joined Orleans membership immediately but passed the nodetype_bake startup gate only at 15:59:37 (2 h 20 min later). Grain placement follows Orleans membership, not k8s readiness, so _UserActivity activations landed on the mid-bake silo where route dispatches sit saturated at 64 in-flight behind stalled _Activity compiles (#1172's exact state, reconfirmed live on the 19:28 roll's pod). Zero occurrences outside such windows; the RLS/typo/deleted-node hypotheses are falsified.

    The fix lands with #1172 (route-slot starvation root cause); exposure is already reduced by #1173 (daily roll cadence). Recurrences on an image containing the #1172 fix would be a new fact — reopen then.

  3. systemorph-com commented on Sep 14, 2026

    @systemorph-com
    Contributor

    Reopened — this fault is happening again.

    Still occurring: 407 more since the last update (414 total).

    • Last seen: 2026-09-14 17:45:33Z
    • Pods: memex-portal-deployment-6bd9c46f8b-z9t6r, memex-portal-deployment-59479dc7d9-kmwvr, memex-portal-deployment-686bdb74cb-vj9xl, memex-portal-deployment-cc58dc7c6-ckll8, memex-portal-deployment-bdc9f8dc4-fdkgw, memex-portal-deployment-6bf5d86dc4-zpgpl, memex-portal-deployment-648c756f74-smlsb, memex-portal-deployment-f96d46ddf-zn9nl, memex-portal-deployment-7d54845c86-brdng, memex-portal-deployment-79cddfb6b7-l7gvv, memex-portal-deployment-79cddfb6b7-pjrvx, memex-portal-deployment-74c7d69bf5-l2xtd, memex-portal-deployment-68795ccb45-4dpdk, memex-portal-deployment-68795ccb45-hzj6p, memex-portal-deployment-5d6f77b68c-wc9pw, memex-portal-deployment-5d6f77b68c-vsmvd, memex-portal-deployment-5d6f77b68c-srtqg, memex-portal-deployment-c89ddfbb6-vzqm7, memex-portal-deployment-7b59b7d657-nmtbz, memex-portal-deployment-f47f8cdd-f8fmq, memex-portal-deployment-f47f8cdd-rx8xj, memex-portal-deployment-7cb5549c57-xxg55, memex-portal-deployment-76b967b5fb-pkw5p, memex-portal-deployment-868d765df7-mwmhj, memex-portal-deployment-745df44fc8-drjtp, memex-portal-deployment-999c9c79d-g9wps, memex-portal-deployment-df7ddfdf4-xb9bk, memex-portal-deployment-775748f44d-7xlkm, memex-portal-deployment-6f76b9c79b-9spms, memex-portal-deployment-7c6b48957d-9zc78, memex-portal-deployment-7c6b48957d-xl99h, memex-portal-deployment-799c674567-p5lr8, memex-portal-deployment-b846c4cc8-v77vj, memex-portal-deployment-856f765d66-47gs2, memex-portal-deployment-7b747dbdb-5526x, memex-portal-deployment-7b747dbdb-sshxj, memex-portal-deployment-9bf79b774-tk88b, memex-portal-deployment-9bf79b774-s9sr9, memex-portal-deployment-9bf79b774-bwgqp, memex-portal-deployment-9bf79b774-b8dl6, memex-portal-deployment-9bf79b774-nvnzz, memex-portal-deployment-7f6bf4c7cc-2649s, memex-portal-deployment-67dbc7bc9c-455hx, memex-portal-deployment-85859db964-q5zcm, memex-portal-deployment-85859db964-7sqbk, memex-portal-deployment-85859db964-mgxj7, memex-portal-deployment-55547495d7-c8z9r, memex-portal-deployment-85859db964-xk5gw, memex-portal-deployment-85859db964-ghsbw, memex-portal-deployment-85859db964-wgtgw, memex-portal-deployment-85859db964-rfsd7, memex-portal-deployment-77c854cfcf-rcbtw, memex-portal-deployment-77c854cfcf-ns2r5, memex-portal-deployment-77cfc55bfc-ptd5l, memex-portal-deployment-77cfc55bfc-txpk7, memex-portal-deployment-77cfc55bfc-q4f9r, memex-portal-deployment-776b97b9fb-9xq2k, memex-portal-deployment-7fd9668b69-jwzzl
    Recent log lines
    2026-09-03 17:32:48Z memex-portal-deployment-77cfc55bfc-q4f9r fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=AgenticOffice/01-Willkommen
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/AgenticOffice_01-Willkommen' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    2026-09-07 22:17:58Z memex-portal-deployment-776b97b9fb-9xq2k fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=rbuergi path=rbuergi
          System.TimeoutException: Update aborted: no initial state arrived for 'rbuergi/_UserActivity/rbuergi' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    2026-09-14 17:45:33Z memex-portal-deployment-7fd9668b69-jwzzl fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=sglauser/AgenticOffice/01-Willkommen
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/sglauser_AgenticOffice_01-Willkommen' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    
  4. rbuergi commented on Sep 14, 2026

    @rbuergi
    Contributor

    2026-09-14 — live, the 2026-08-10 verdict no longer covers the population, and the failing write is pinned at the queue level

    This was closed on 2026-08-10 as a duplicate of #1172 (roll-window route starvation), with "Recurrences on an image containing the #1172 fix would be a new fact — reopen then." That condition is met, and the evidence has moved.

    The incident, read today on the control instance

    get @Admin/_LogIncident/7473a637daf1e169 (memex.systemorph.com), 2026-09-14 18:1xZ:

    category:    MeshWeaver.Graph.ActivityTracking
    exception:   System.TimeoutException
    occurrences: 414     firstSeen 2026-08-10T13:49:50Z     lastSeen 2026-09-14T17:45:33Z
    pods:        57
    

    The fold is honest here: all ten retained samples are the same category, the same exception type and the same message shape, differing only in user and path. This is one defect, and it is live.

    The roll-window explanation does not cover it

    The 08-10 argument was that every occurrence then known lay inside the 13:38:56 roll's join-to-Ready window. The retained ring now spans 2026-09-02T19:22Z → 2026-09-14T17:45Z across many pods, and the last one landed on memex-portal-deployment-7fd9668b69-jwzzl — a pod that already appears in another incident's samples at 2026-09-13T22:03Z, i.e. up for ~20 h at the time. It may still be a contributor; it is no longer the explanation.

    The failing write, pinned

    A Logs instance action on the control instance (read-only; no cluster access) over the 17:45Z window returned, from the same pod:

    17:45:08.832Z  [UpdateQueue] ADVANCE_WITHOUT_HANDOFF path=sglauser/_UserActivity/sglauser_AgenticOffice_01-Willkommen seq=30538 bound=5000ms
    17:45:33.831Z  [UpdateQueue] FAILED                 path=sglauser/_UserActivity/sglauser_AgenticOffice_01-Willkommen seq=30538 elapsedMs=30004
    

    Same seq. So the write had its queue slot from ~17:45:03.83 and its base read simply never completed — it was not sitting behind a predecessor, and the owner had not acknowledged it even at +5 s.

    Two more readings worth having:

    • It concentrates on the HOT paths. Every retained sample is either {user}/_UserActivity/{user} — the login node written on every cold page load; mine is at version 6498 — or a page that user revisits (Store, AgenticOffice/01-Willkommen). Cold paths do not appear.
    • In a 4-hour window there is no [ROUTE] NotFound, no Access denied and no [SYNC_STREAM] OnError naming any _UserActivity path. (Positive control on the same query: the 17:45:33Z abort line itself came back, so the zero is readable.)

    Why it could not be attributed, and what just landed

    The exception lists four suspects. There are really only two shapes of silence, and they are opposite defects:

    what the mirror did what it means where to look
    NO change item at all the owner never answered the subscribe ACTIVATION and ROUTING
    N change items, none carrying the node the owner IS answering; its view of the path is EMPTY readability FROM THE OWNER — the initial read's identity/RLS, or a MeshDataSource that did not load it

    🚨 Row 1 rules the node's content and its grants OUT, not in: an absent node and one the reader may not see both still produce a change item that carries no node. So suspects (1)–(3) of the message's own list are impossible in that half — and until now the log could not say which half you were in, because both raised the same bare TimeoutException("The operation has timed out.").

    #4342 closes that gap: the base read counts what the mirror produced and says so. No bound changed, no retry, nothing swallowed; three negative controls watched red. Conserved as Doc/Architecture/BaseStateTimeoutCensus.

    Staying open, and on what

    #4342 is an INSTRUMENT, not a fix — the fault is still live at 414 occurrences. Closing this needs, in order:

    1. a roll of memex-cloud carrying fix(#1174): a base-state timeout says WHICH silence it waited on #4342 (deploy decision, not mine);
    2. one reading of the next occurrence, which will name its half;
    3. the fix for that half.

    All reads read-only (get / search on the control instance, one Logs instance action, curl /api/version). No mesh data was changed; no cluster access was used.

  5. added a commit that references this issue on Sep 14, 2026
  6. rbuergi commented on Sep 14, 2026

    @rbuergi
    Contributor

    Correction to my comment above — the zero branch does NOT rule the node's content out

    The review on #4342 caught a real error in the fork I posted 25 minutes ago, and it is the direction that matters, so correcting it here rather than leaving the wrong table standing.

    What I wrote: that "NO change item at all" means the owner never answered the subscribe, and therefore rules the node's content and its grants OUT.

    Why that is wrong. This seam observes ChangeItem FRAMES, not the subscribe acknowledgement — and a fresh stream acknowledges IMMEDIATELY, deliberately, before its first Full comes out of the reduce's own hydration. JsonSynchronizationStream says so verbatim:

    🚨 A FRESH stream acks IMMEDIATELY, and the asymmetry with the re-assert path above is deliberate (#3058). … its first Full comes out of the reduce's own hydration, which is IO-bound and unbounded (a cold data source, a per-node hub activating).

    So zero frames means no snapshot ever hydrated, and an owner that acked and then produced nothing — a cold data source, a per-node hub still activating, an initial read that yielded nothing — is indistinguishable from one that never answered. My table would have sent a reader away from exactly the MeshDataSource/initial-load causes they must still consider.

    The corrected fork:

    what the mirror did what it means where to look
    NO change item at all no snapshot ever hydrated still BOTH — the owner's activation/routing AND its initial read
    N change items, none carrying the node frames ARE arriving, so the subscription is established and producing, and the owner's view of this path is EMPTY readability FROM THE OWNER — the initial read's identity/RLS, or a MeshDataSource that did not load it

    Branch two is the one that excludes something. Branch one narrows nothing away — and the shipped message now says that in its own sentence rather than implying a verdict.

    Everything else in my comment above stands as measured: 414 occurrences, lastSeen 2026-09-14T17:45:33Z, the seq=30538 pair, the hot-path concentration, and the fact that the 2026-08-10 roll-window verdict no longer covers the population. Corrected in #4342 at 35b5243, in the message, the XML doc, the doc page and the What's New entry.

  7. rbuergi commented on Sep 14, 2026

    @rbuergi
    Contributor

    #4342 merged — and this issue STAYS OPEN

    Landed on main as 48a3bee143363cabf55c01dd44f990aa5426138f (PR #4342, head 35b524302b00ca649e5a2de3259ee2b57ba77d29, both verified as ancestors of origin/main). The shipped text is the post-review one, not my first draft.

    🚨 This is a better DIAGNOSTIC, not a fix. The write still fails. #4342 makes the base-state timeout name what it waited on; it does nothing to make the write succeed, and the 414 occurrences are untouched by it. Do not read the merge as a resolution.

    What changed

    BaseStateSource now counts what the mirror produced inside the bound and says so:

    what the mirror did what it means where to look
    NO change item at all no snapshot ever hydrated still BOTH — the owner's activation/routing AND its initial read
    N change items, none carrying the node frames ARE arriving, so the subscription is established and producing, and the owner's view of this path is EMPTY readability FROM THE OWNER — the initial read's identity/RLS, or a MeshDataSource that did not load it

    No bound moved, nothing retries, nothing is swallowed. Conserved as Doc/Architecture/BaseStateTimeoutCensus.

    What still has to happen, in order

    1. A roll of memex-cloud carrying 48a3bee. Not imminent, and that is now measured rather than assumed: the fleet's publication has not SEALED since 12:53Z (Systemorph/MeshWeaver.Plugins#1872), and at 19:01Z both portals still served 3.0.0+c84c6c055…. Until that moves, every new sample the watcher folds here comes from an image without the census — a recurrence is not a new fact while that is true.
    2. One reading of the next occurrence, which will name its half.
    3. The fix for that half. That is what closes this issue.

    The measurements that stand

    Unchanged from my comment above, and they are what the next session should start from rather than re-deriving:

    • Admin/_LogIncident/7473a637daf1e169: 414 occurrences since 2026-08-10 across 57 pods, lastSeen 2026-09-14T17:45:33Z.
    • The failing write, pinned at the queue level on pod …7fd9668b69-jwzzl: [UpdateQueue] ADVANCE_WITHOUT_HANDOFF … seq=30538 bound=5000ms at 17:45:08.832Z and [UpdateQueue] FAILED … seq=30538 elapsedMs=30004 at 17:45:33.831Z — same seq, so it was dispatched and never got a base; it was not queued behind a predecessor.
    • The 2026-08-10 roll-window verdict (duplicate of RoutingGrain route dispatches hang at 64 in-flight when _Activity compilation stalls #1172) no longer covers the population: the retained ring spans 2026-09-02 → 2026-09-14 on long-lived pods.
    • The failures concentrate on hot paths — {user}/_UserActivity/{user} (one at version 6498) and repeatedly-visited pages. Cold paths do not appear. This is a correlation, not an established cause; the census is what will decide it.
  8. rbuergi commented on Sep 14, 2026

    @rbuergi
    Contributor

    Triage 2026-09-14: #4342 is an instrument, not a fix (confirmed), and there IS a shipped mechanism that predicts the hot-path concentration the thread calls unexplained

    48a3bee143 (#4342) touched the message, docs and tests only — BaseStateWaitBound is still 30 s (MeshNodeStreamExtensions.cs:147), BaseStateSource (:232) has the same .Timeout and no retry, and the activity writer (MeshWeaver.Graph/MeshNodeExtensions.cs:380) still dies at the bound.

    The correlation "hot paths only" has a mechanism in this repo: Workspace.EvictForPath (src/MeshWeaver.Data/Workspace.cs:337) fires on EVERY change-feed Created/Updated/Deleted and evicts the mirror unconditionally — including the one the writer itself just used — so the next write resolves a fresh mirror: another SubscribeRequest, another initial-state round trip, another pair of sync/ hubs, per write (the remarks at Workspace.cs:315-336 measure six progress writes minting 7 client + 11 owner sync/ hubs; Doc/Architecture/LiveMirrorsAndTheChangeFeed documents it and records why gating EvictForPath on liveness LOST writes). {user}/_UserActivity/{user} at version 6498 has paid ~6498 evict → dispose → re-subscribe cycles; a cold path pays one. Every hot write therefore hydrates a brand-new mirror inside the 30 s bound while the one it just destroyed is being torn down on the same owner address — which predicts census branch one ("no change item reached the mirror") for the next occurrence. Falsifiable in one line once a replica carrying 48a3bee is rolled.

    Fix shape, per the doc: make the write's base version-aware (wait for the mirror to reach the Version the MeshChangeEvent carries) so EvictForPath stops being the freshness barrier; not a liveness gate on the eviction, which is measured to lose writes.

  9. added a commit that references this issue on Sep 15, 2026
  10. systemorph-com commented on Sep 15, 2026

    @systemorph-com
    Contributor

    Reopened — this fault is happening again.

    Still occurring: 2 more since the last update (416 total).

    • Last seen: 2026-09-15 16:32:14Z
    • Pods: memex-portal-deployment-6bd9c46f8b-z9t6r, memex-portal-deployment-59479dc7d9-kmwvr, memex-portal-deployment-686bdb74cb-vj9xl, memex-portal-deployment-cc58dc7c6-ckll8, memex-portal-deployment-bdc9f8dc4-fdkgw, memex-portal-deployment-6bf5d86dc4-zpgpl, memex-portal-deployment-648c756f74-smlsb, memex-portal-deployment-f96d46ddf-zn9nl, memex-portal-deployment-7d54845c86-brdng, memex-portal-deployment-79cddfb6b7-l7gvv, memex-portal-deployment-79cddfb6b7-pjrvx, memex-portal-deployment-74c7d69bf5-l2xtd, memex-portal-deployment-68795ccb45-4dpdk, memex-portal-deployment-68795ccb45-hzj6p, memex-portal-deployment-5d6f77b68c-wc9pw, memex-portal-deployment-5d6f77b68c-vsmvd, memex-portal-deployment-5d6f77b68c-srtqg, memex-portal-deployment-c89ddfbb6-vzqm7, memex-portal-deployment-7b59b7d657-nmtbz, memex-portal-deployment-f47f8cdd-f8fmq, memex-portal-deployment-f47f8cdd-rx8xj, memex-portal-deployment-7cb5549c57-xxg55, memex-portal-deployment-76b967b5fb-pkw5p, memex-portal-deployment-868d765df7-mwmhj, memex-portal-deployment-745df44fc8-drjtp, memex-portal-deployment-999c9c79d-g9wps, memex-portal-deployment-df7ddfdf4-xb9bk, memex-portal-deployment-775748f44d-7xlkm, memex-portal-deployment-6f76b9c79b-9spms, memex-portal-deployment-7c6b48957d-9zc78, memex-portal-deployment-7c6b48957d-xl99h, memex-portal-deployment-799c674567-p5lr8, memex-portal-deployment-b846c4cc8-v77vj, memex-portal-deployment-856f765d66-47gs2, memex-portal-deployment-7b747dbdb-5526x, memex-portal-deployment-7b747dbdb-sshxj, memex-portal-deployment-9bf79b774-tk88b, memex-portal-deployment-9bf79b774-s9sr9, memex-portal-deployment-9bf79b774-bwgqp, memex-portal-deployment-9bf79b774-b8dl6, memex-portal-deployment-9bf79b774-nvnzz, memex-portal-deployment-7f6bf4c7cc-2649s, memex-portal-deployment-67dbc7bc9c-455hx, memex-portal-deployment-85859db964-q5zcm, memex-portal-deployment-85859db964-7sqbk, memex-portal-deployment-85859db964-mgxj7, memex-portal-deployment-55547495d7-c8z9r, memex-portal-deployment-85859db964-xk5gw, memex-portal-deployment-85859db964-ghsbw, memex-portal-deployment-85859db964-wgtgw, memex-portal-deployment-85859db964-rfsd7, memex-portal-deployment-77c854cfcf-rcbtw, memex-portal-deployment-77c854cfcf-ns2r5, memex-portal-deployment-77cfc55bfc-ptd5l, memex-portal-deployment-77cfc55bfc-txpk7, memex-portal-deployment-77cfc55bfc-q4f9r, memex-portal-deployment-776b97b9fb-9xq2k, memex-portal-deployment-7fd9668b69-jwzzl
    Recent log lines
    2026-09-14 17:45:33Z memex-portal-deployment-7fd9668b69-jwzzl fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=sglauser/AgenticOffice/01-Willkommen
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/sglauser_AgenticOffice_01-Willkommen' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    2026-09-14 23:24:15Z memex-portal-deployment-7fd9668b69-jwzzl fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=sglauser/AgenticOffice/01-Willkommen/Dokumente/MeinFirmenprofil
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/sglauser_AgenticOffice_01-Willkommen_Dokumente_MeinFirmenprofil' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    2026-09-15 16:32:14Z memex-portal-deployment-7fd9668b69-jwzzl fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=sglauser/AgenticOffice/01-Willkommen/Exercise/WasWeissDerAgent
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/sglauser_AgenticOffice_01-Willkommen_Exercise_WasWeissDerAgent' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    
  11. rbuergi commented on Sep 15, 2026

    @rbuergi
    Contributor

    Triage 2026-09-15 17:1xZ: the reopen at 16:33Z is expected, because no pod runs the fix yet.

    So this stays open until memex rolls past both. The closing check then is: this incident's occurrences stop advancing on pods running a set that carries #4428.

    🤖 Generated with Claude Code

  12. 9 remaining items

  13. systemorph-com commented on Sep 18, 2026

    @systemorph-com
    Contributor

    Still occurring: 1 more since the last update (425 total).

    • Last seen: 2026-09-18 17:04:23Z
    • Pods: memex-portal-deployment-6bd9c46f8b-z9t6r, memex-portal-deployment-59479dc7d9-kmwvr, memex-portal-deployment-686bdb74cb-vj9xl, memex-portal-deployment-cc58dc7c6-ckll8, memex-portal-deployment-bdc9f8dc4-fdkgw, memex-portal-deployment-6bf5d86dc4-zpgpl, memex-portal-deployment-648c756f74-smlsb, memex-portal-deployment-f96d46ddf-zn9nl, memex-portal-deployment-7d54845c86-brdng, memex-portal-deployment-79cddfb6b7-l7gvv, memex-portal-deployment-79cddfb6b7-pjrvx, memex-portal-deployment-74c7d69bf5-l2xtd, memex-portal-deployment-68795ccb45-4dpdk, memex-portal-deployment-68795ccb45-hzj6p, memex-portal-deployment-5d6f77b68c-wc9pw, memex-portal-deployment-5d6f77b68c-vsmvd, memex-portal-deployment-5d6f77b68c-srtqg, memex-portal-deployment-c89ddfbb6-vzqm7, memex-portal-deployment-7b59b7d657-nmtbz, memex-portal-deployment-f47f8cdd-f8fmq, memex-portal-deployment-f47f8cdd-rx8xj, memex-portal-deployment-7cb5549c57-xxg55, memex-portal-deployment-76b967b5fb-pkw5p, memex-portal-deployment-868d765df7-mwmhj, memex-portal-deployment-745df44fc8-drjtp, memex-portal-deployment-999c9c79d-g9wps, memex-portal-deployment-df7ddfdf4-xb9bk, memex-portal-deployment-775748f44d-7xlkm, memex-portal-deployment-6f76b9c79b-9spms, memex-portal-deployment-7c6b48957d-9zc78, memex-portal-deployment-7c6b48957d-xl99h, memex-portal-deployment-799c674567-p5lr8, memex-portal-deployment-b846c4cc8-v77vj, memex-portal-deployment-856f765d66-47gs2, memex-portal-deployment-7b747dbdb-5526x, memex-portal-deployment-7b747dbdb-sshxj, memex-portal-deployment-9bf79b774-tk88b, memex-portal-deployment-9bf79b774-s9sr9, memex-portal-deployment-9bf79b774-bwgqp, memex-portal-deployment-9bf79b774-b8dl6, memex-portal-deployment-9bf79b774-nvnzz, memex-portal-deployment-7f6bf4c7cc-2649s, memex-portal-deployment-67dbc7bc9c-455hx, memex-portal-deployment-85859db964-q5zcm, memex-portal-deployment-85859db964-7sqbk, memex-portal-deployment-85859db964-mgxj7, memex-portal-deployment-55547495d7-c8z9r, memex-portal-deployment-85859db964-xk5gw, memex-portal-deployment-85859db964-ghsbw, memex-portal-deployment-85859db964-wgtgw, memex-portal-deployment-85859db964-rfsd7, memex-portal-deployment-77c854cfcf-rcbtw, memex-portal-deployment-77c854cfcf-ns2r5, memex-portal-deployment-77cfc55bfc-ptd5l, memex-portal-deployment-77cfc55bfc-txpk7, memex-portal-deployment-77cfc55bfc-q4f9r, memex-portal-deployment-776b97b9fb-9xq2k, memex-portal-deployment-7fd9668b69-jwzzl, memex-portal-deployment-fb6488b5f-x7bv5
    Recent log lines
    2026-09-15 22:20:35Z memex-portal-deployment-7fd9668b69-jwzzl fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=Portfolio
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/Portfolio' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    2026-09-15 22:53:51Z memex-portal-deployment-7fd9668b69-jwzzl fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=sglauser path=Portfolio
          System.TimeoutException: Update aborted: no initial state arrived for 'sglauser/_UserActivity/Portfolio' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence.
           ---> System.TimeoutException: The operation has timed out.
             --- End of inner exception stack trace ---
    2026-09-18 17:04:23Z memex-portal-deployment-fb6488b5f-x7bv5 fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=rsalzmann path=rsalzmann
          System.TimeoutException: Update aborted: no initial state arrived for 'rsalzmann/_UserActivity/rsalzmann' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence. NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
           ---> MeshWeaver.Mesh.MeshNodeStreamHandle+BaseStateTimeoutException: NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
             --- End of inner exception stack trace ---
    
  14. rbuergi commented on Sep 19, 2026

    @rbuergi
    Contributor

    Roll-gated close review, 2026-09-19 — HELD OPEN

    This issue was on a list of twelve bot-filed incidents whose fixes merged after the 2026-09-12 freeze commit c84c6c05 and which were believed to be open only because memex.meshweaver.cloud had not rolled. The roll has happened. I checked three clauses before closing anything. This one is not closable, and the reason that dominates is the same for all twelve.

    (a) Ancestry — PASSES

    memex.meshweaver.cloud is running commit c25f86ae85b7050f0fffa45d81444cc69cbb64d8 — image 3.0.0-ci.8969, 3 of 3 replicas on one generation, converged: true, pods started 08:34:53 / 08:39:58 / 08:39:59Z, read from Ops/Status/memex-cloud sampled 10:24:54Z. Verified locally with git merge-base --is-ancestor:

    • 141e5fdc91 — ancestor of c25f86ae85b7
    • 13ac6a0210 — ancestor of c25f86ae85b7
    • 48a3bee143 — ancestor of c25f86ae85b7

    The local clone is shallow (grafted at bc4b1bd892, 2026-08-27), which can return a false "no" for a pre-graft commit. Every commit above is dated 2026-09-13 or later, i.e. well inside the grafted history, so none of these answers is affected.

    (c) Thread does not call the fix partial

    (c) FAILS. Your 2026-09-16 comment on #4468 is explicit: "🚨 This is a better instrument plus two silent-drop fixes. It does NOT make the #1174 write succeed, and the occurrence count is untouched by it." The 2026-09-18 triage adds: "stays open. The blocker ... is now HALF cleared, and the half that matters is not."

    Last seen for this fingerprint (Admin/_LogIncident/7473a637daf1e169, read on the control instance): 2026-09-18T17:04:23.980Z, 425 occurrences, namespace: memex-cloud. That is before the 08:00Z settle line, and the newest of its retained samples carries the same timestamp. The node was readable — this is a real reading, not an absent one.


    🚨 (b) No recurrence since the roll — CANNOT BE ESTABLISHED. The instrument is dark.

    A silence is only evidence if the thing that would have broken it is still working. It is not.

    No incident anywhere in the population has folded a sighting since 2026-09-19T07:28:51Z — before the current replicas even started — and the single node written since 08:00Z has its lastSeen frozen at 05:43:46Z, roughly 4 h 45 m before this comment. I checked the whole readable Admin/_LogIncident population on the control instance, sorted by lastModified descending. Since a fold is what writes the node, lastSeen <= lastModified, so lastModified is a sound upper bound: only one node in the entire population has been written since 08:00Z — e4a97855ab595beb, the RoutingGrain back-pressure incident, which is the highest-volume fingerprint in the fleet at 13,108,032 lifetime occurrences and severity Critical.

    I probed it directly as the positive control. Its version advanced across my reads (51427 → 51430 → 51434, lastModified 10:12:29Z → 10:26:28Z → 10:27:29Z), so something is still writing the node — but across two gets 4 m 35 s apart:

    content.lastSeen      2026-09-19T05:43:46.667Z   ->  2026-09-19T05:43:46.667Z   (no change)
    content.occurrences   13108032                   ->  13108032                   (no change)
    max samples[].timestamp  2026-09-19T05:43:46.667Z  (all 10 samples 05:21:00Z - 05:43:46Z)
    

    A fingerprint that has fired 13.1 million times has folded zero sightings in 4 h 44 m. The writes that do land are triage bookkeeping — the node carries a standing content.error: "Cannot comment: the incident has no repository." since 2026-09-17T19:09:17Z. Rewrites without an occurrence advance are a known shape here: fingerprint 70a700c6cfe6c28a has a lastModified 11.6 days later than its lastSeen with its counter unmoved. A high version is not evidence of a recent recurrence.

    The control that settles it — the same event class on both sides of the change. memex-cloud rolled or restarted six times this morning:

    time (UTC) action incident folds recorded
    05:03Z Roll → 3.0.0-ci.8955 (+ 05:08Z migration reconcile) ~28
    05:50Z, 06:14Z Restart ×2 0
    06:35Z Roll → 3.0.0-ci.8963 0
    07:39Z Roll → 3.0.0-ci.8966 0
    08:32Z Roll → 3.0.0-ci.8969 (pods up 08:34:53 / 08:39:58 / 08:39:59Z) 0

    The 05:03Z roll produced a textbook roll signature — DbVersionGate: DB migration incomplete, Host: Hosting failed to start, MemexConfiguration: Startup was cancelled, an ObjectDisposedException wave across SiloHealthMonitor / OrleansRoutingService / Messaging / Grain / MessageService, IoPoolSiloTeardown, nodetype_bake Unhealthy, and the Orleans memory-* queue timeouts — 28 folds between 05:07:58Z and 05:47:25Z. The four later rolls produced none. Same event class, same instrument, opposite result.

    To state the bound exactly: the last incident-node write of any kind across the population was 07:28:51Z, and the only node written after that is the bookkeeping one above. A sighting is what writes the node — so nothing has been recorded anywhere in the ~3 h since 07:28:51Z, a window that wholly contains the post-roll period (replicas up 08:34–08:40Z). Whether ingestion died at 05:47Z or at 07:28Z does not change this issue's answer: either way there is no observation window after the roll.

    That the drop is uniform across fingerprints these twelve fixes cannot touch — Orleans MemoryAdapterFactory timeouts, DbVersionGate, Hosting failed to start — rules out "we fixed everything". The mesh itself is demonstrably alive: Admin/UpdatePolicy and Admin/_Build/* were written at 10:28Z, Ops/Status/* at 10:24Z.

    So the required positive control fails: across the entire readable population I could not find one incident that fired after the settle line. Per the rule I was working to, that reading is indistinguishable from "the watcher stopped", and it would be wrong to convert it into twelve closures.

    (Honest limit: I could not find a health entry naming log ingestion as failed. Every /health healthDetail on Ops/Status/memex-cloud is stored truncated mid-source-discovery — ~7 of 16 checks are visible — so an ingestion check past the cut would be invisible. An absent entry is not a clean one. The ingestion stall is inferred from the fold record above, not from a health verdict.)

    Verdict

    Stays open. Clause (b) is unmet for every one of the twelve. This issue also fails clause (c) above, so it would stay open even with a working watcher.

    Nothing here is a statement that the defect is still live — it may well be fixed. It is a statement that the evidence required to say so does not currently exist, and that the incident-ingestion stall is itself worth a ticket: the portal has been rolling all morning with its recurrence watcher recording nothing.

    No labels, state or assignees were changed. Read-only apart from this comment.

  15. rbuergi commented on Sep 19, 2026

    @rbuergi
    Contributor

    Source-level mechanism, 2026-09-19 — the write takes its branch from an eventually-consistent query's POSITIVE, and this repo already documents that shape as retired-by-design

    Every prior comment here concluded the next step is a production reading. This one does not need one: the branch that produces the timeout is decidable from source, and the platform already contains the verb that exists to remove it.

    What the failing path actually does

    MeshWeaver.Graph/MeshNodeExtensions.cs:

    line what
    286 var stream = workspace.GetMeshNodeStream(activityPath);
    320-323 existence established by workspace.GetQuery("UserActivity|<path>", "path:<path> nodeType:UserActivity …") — the eventually-consistent index
    379 if (existing != null)
    392 return AsCaller(() => stream.Update(FoldOntoLive)); ← the 30 s wait
    430 the mirror branch: CreateNode → NodeAlreadyExists race → stream.Update(FoldOntoLive)

    The two branches do not establish existence the same way. At 430 the owner has just refused the create with Node already exists: — durable truth, serialised by the hub that owns the row. At 392 the only evidence is the query index.

    The code already knows that index is stale-prone: its own comment at 378 says record.AccessCount is "the count derived from the EVENTUALLY-CONSISTENT query snapshot above". It handles the stale negative (create → already-exists → fold to update). Nothing handles the stale or ghost positive, and that is the branch that lands on stream.Update.

    The repo already states this rule — for the delete side

    MeshWeaver.Mesh.Contract/MeshExtensions.cs:3315, written by #4668:

    "It cannot be fixed by asking first. A client-side existence check is precisely the shape CreateOrUpdateNodeRequest exists to retire on the create side: the check's negative can be stale by the time the delete lands, and a point read of an absent node is itself a framework defect (it terminates the stream on a routing NotFound and arms the storm-breaker for that path). The operation is where the race is decidable, because the owning hub serialises it."

    CreateOrUpdateNodeRequest's own summary says the same in the affirmative — it is the "single global verb … so callers don't replay the existence dance". TrackActivity replays it.

    Why that verb is the one that matters here — it carries the repair for this exact condition

    The upsert does not consult the query index. It establishes existence from a persistence read (MeshExtensions.cs:5851-5868, trail stages UPSERT_READ absent → create / UPSERT_READ existing → update). And its update leg floors the version on that durable row, for a reason it states verbatim (~6270):

    "When the owner's live snapshot is BEHIND durable truth — a hub that could not hydrate the stored node and started from a blank MeshNode.FromPath — the mint comes out at 1, the guard refuses it, and the owner's AdoptDurableTruth rebase then re-adopts the stored row … That is not a corner case, it is how a GHOST PARTITION ROOT becomes permanent (#902/#638)."

    "A hub that could not hydrate the stored node" is, word for word, the condition the newest sample on this issue reports:

    BaseStateTimeoutException: NO change item at all reached the mirror inside the bound — no snapshot ever hydrated.

    So the one code path in the platform that repairs a node whose owner cannot hydrate it is the path this caller does not take.

    🚨 Honest limits — what this does and does not establish

    • It does not prove the ghost/stale positive is what fired on 2026-09-18. BaseStateTimeoutException's own text says a cold data source, a still-activating hub and an initial read yielding nothing are indistinguishable there. This names a mechanism the code can produce deterministically; it does not close the other three.
    • It does remove the dependency on a production reading for the fix, because the remedy is prescribed by the platform's own rule regardless of which of the four causes fires: the caller must not decide create-vs-update from the index.
    • The discriminator, if someone does get a reading: the upsert trail says UPSERT_READ absent vs existing, which is durable truth. The query cannot answer that question at all.

    🚧 The blocker — and it is a real gap in the verb, not in this caller

    Routing TrackActivity through CreateOrUpdateNodeRequest loses the counter increment, and neither payload mode can express it:

    • Full-instance mode merges via UpdateAccordingToSourceNode, which takes Content = sourceNode.Content ?? state.Content — content wholesale. FoldOntoLive's whole purpose (:356, guarding A no-op stream.Update never completes its writer — one of five concurrent activity tracks never LEAVEs, and its increment is lost #3001) is that AccessCount is re-read off the live node inside the owner-serialised lambda. A full-instance upsert would write the stale query-derived count instead.
    • Patch mode is documented for "incremental edits where multiple writers may race on the same node — log lines, view-count bumps, status-flip patterns". An AccessCount bump is a view-count bump — but JSON Patch has no increment operation, so the value still has to be computed from a stale read before the request is sent. The documented use case is not actually served by either mode.
    • MeshNodeStreamHandle has three Update overloads (MeshNodeStreamExtensions.cs:1246, 1268, 1355) and none takes a create-if-missing seed, so there is no third route that keeps the fold owner-side.

    Proposed next step

    Give the upsert an owner-side fold — the merge lambda shape stream.Update already has — so a counter bump can go through the one verb that decides existence against durable truth and carries the AdoptDurableTruth repair. Then move TrackActivity's :379/:392 branch onto it and delete the query's role in choosing the write.

    That is a framework change with a real design surface, so I am not landing it unilaterally on a cold-login hot path. Filing it as the concrete follow-up rather than leaving this issue resting on "needs a roll".

    Nothing closed. No labels, state or assignees changed.

    Source-level triage 2026-09-19 by Claude Opus 5 — read-only; every line/quote above is from the current main.

  16. added
    bugSomething isn't working
    area:meshCore subsystem: the mesh - nodes, partitions, addressing, activation
    sev:MMedium - secondary path broken, or easy workaround
    on Sep 20, 2026
  17. rbuergi commented on Sep 20, 2026

    @rbuergi
    Contributor

    The blocker named on 2026-09-19 has a shape now — Doc/Architecture/ExpressingAWrite (PR #4970)

    The 19:22Z comment localised this to one line (MeshNodeExtensions.cs:379/392 decides create-vs-update
    from the eventually-consistent query index) and filed the framework gap as #4928, stating the reason it
    could not simply be fixed: "a delegate cannot cross the wire."

    That is true of a delegate and not of an expression tree. A tree is analysable, and what it
    lowers to is JSON Patch operations — which do cross the wire, and which the owner applies inside the
    Update lambda the upsert's update leg already runs (MeshExtensions.cs:~6325). So the fix needs
    no new execution point: every field except Content is already folded owner-side there; Content is
    the one taken wholesale.

    The design is committed in #4970. It is design only — nothing is implemented, and this issue stays
    blocked on #4928.

    One thing the design changes about the eventual fix here

    FoldOntoLive (:356) does three different things, and only one of them is an increment:

    field fold
    AccessCount sum — live + 1
    FirstAccessedAt keep-live-if-present
    LastAccessedAt take the newer

    So whatever lands for #4928 has to carry more than "increment". A lambda expresses all three
    naturally, which is the argument for making the lambda the authoring surface rather than hand-writing
    patch ops at the call site.

    Status unchanged

    Still open, still 425 occurrences, still gated on #4928. Nothing here is a production reading, and the
    19:22Z comment's honest-limits section still stands: this names a mechanism the code can produce
    deterministically, and does not close the other three causes BaseStateTimeoutException cannot
    distinguish.

    Cross-reference 2026-09-20 by Claude Opus 5 — read-only.

  18. added a commit that references this issue on Sep 20, 2026
  19. systemorph-com commented on Sep 21, 2026

    @systemorph-com
    Contributor

    Still occurring: 3 more since the last update (428 total).

    • Last seen: 2026-09-20 22:25:44Z
    • Pods: memex-portal-deployment-75b545bbd-nssvp, memex-portal-deployment-6bd9c46f8b-z9t6r, memex-portal-deployment-59479dc7d9-kmwvr, memex-portal-deployment-686bdb74cb-vj9xl, memex-portal-deployment-cc58dc7c6-ckll8, memex-portal-deployment-bdc9f8dc4-fdkgw, memex-portal-deployment-6bf5d86dc4-zpgpl, memex-portal-deployment-648c756f74-smlsb, memex-portal-deployment-f96d46ddf-zn9nl, memex-portal-deployment-7d54845c86-brdng, memex-portal-deployment-79cddfb6b7-l7gvv, memex-portal-deployment-79cddfb6b7-pjrvx, memex-portal-deployment-74c7d69bf5-l2xtd, memex-portal-deployment-68795ccb45-4dpdk, memex-portal-deployment-68795ccb45-hzj6p, memex-portal-deployment-5d6f77b68c-wc9pw, memex-portal-deployment-5d6f77b68c-vsmvd, memex-portal-deployment-5d6f77b68c-srtqg, memex-portal-deployment-c89ddfbb6-vzqm7, memex-portal-deployment-7b59b7d657-nmtbz, memex-portal-deployment-f47f8cdd-f8fmq, memex-portal-deployment-f47f8cdd-rx8xj, memex-portal-deployment-7cb5549c57-xxg55, memex-portal-deployment-76b967b5fb-pkw5p, memex-portal-deployment-868d765df7-mwmhj, memex-portal-deployment-745df44fc8-drjtp, memex-portal-deployment-999c9c79d-g9wps, memex-portal-deployment-df7ddfdf4-xb9bk, memex-portal-deployment-775748f44d-7xlkm, memex-portal-deployment-6f76b9c79b-9spms, memex-portal-deployment-7c6b48957d-9zc78, memex-portal-deployment-7c6b48957d-xl99h, memex-portal-deployment-799c674567-p5lr8, memex-portal-deployment-b846c4cc8-v77vj, memex-portal-deployment-856f765d66-47gs2, memex-portal-deployment-7b747dbdb-5526x, memex-portal-deployment-7b747dbdb-sshxj, memex-portal-deployment-9bf79b774-tk88b, memex-portal-deployment-9bf79b774-s9sr9, memex-portal-deployment-9bf79b774-bwgqp, memex-portal-deployment-9bf79b774-b8dl6, memex-portal-deployment-9bf79b774-nvnzz, memex-portal-deployment-7f6bf4c7cc-2649s, memex-portal-deployment-67dbc7bc9c-455hx, memex-portal-deployment-85859db964-q5zcm, memex-portal-deployment-85859db964-7sqbk, memex-portal-deployment-85859db964-mgxj7, memex-portal-deployment-55547495d7-c8z9r, memex-portal-deployment-85859db964-xk5gw, memex-portal-deployment-85859db964-ghsbw, memex-portal-deployment-85859db964-wgtgw, memex-portal-deployment-85859db964-rfsd7, memex-portal-deployment-77c854cfcf-rcbtw, memex-portal-deployment-77c854cfcf-ns2r5, memex-portal-deployment-77cfc55bfc-ptd5l, memex-portal-deployment-77cfc55bfc-txpk7, memex-portal-deployment-77cfc55bfc-q4f9r, memex-portal-deployment-776b97b9fb-9xq2k, memex-portal-deployment-7fd9668b69-jwzzl, memex-portal-deployment-fb6488b5f-x7bv5
    Recent log lines
    2026-09-20 22:25:33Z memex-portal-deployment-75b545bbd-nssvp fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=rbuergi path=rbuergi
          System.TimeoutException: Update aborted: no initial state arrived for 'rbuergi/_UserActivity/rbuergi' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence. NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
           ---> MeshWeaver.Mesh.MeshNodeStreamHandle+BaseStateTimeoutException: NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
             --- End of inner exception stack trace ---
    2026-09-20 22:25:38Z memex-portal-deployment-75b545bbd-nssvp fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=rbuergi path=rbuergi
          System.TimeoutException: Update aborted: no initial state arrived for 'rbuergi/_UserActivity/rbuergi' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence. NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
           ---> MeshWeaver.Mesh.MeshNodeStreamHandle+BaseStateTimeoutException: NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
             --- End of inner exception stack trace ---
    2026-09-20 22:25:44Z memex-portal-deployment-75b545bbd-nssvp fail: MeshWeaver.Graph.ActivityTracking[0]
          Failed to track activity for user=rbuergi path=BusinessModel/EdgeComputeFleet
          System.TimeoutException: Update aborted: no initial state arrived for 'rbuergi/_UserActivity/BusinessModel_EdgeComputeFleet' within 30s. Likely causes — (1) RLS silently rejected the prior CreateNode, (2) the path is misspelled / points at a namespace no NodeType claims, (3) the node was deleted between create and update, or (4) the per-node hub activated but its MeshDataSource didn't load the node from persistence. NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
           ---> MeshWeaver.Mesh.MeshNodeStreamHandle+BaseStateTimeoutException: NO change item at all reached the mirror inside the bound — no snapshot ever hydrated. This does NOT establish that the owner never answered: a fresh subscribe is ACKNOWLEDGED BEFORE hydration, so an owner that acked and then produced no frame (a cold data source, a per-node hub still activating, an initial read that yielded nothing) reads identically here. Both the owner's activation/routing AND its initial read are still in scope.
             --- End of inner exception stack trace ---
    

    Re-addressed by the current identity function: this incident inherited 7473a637daf1e169 (Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.

  20. rbuergi commented on Sep 22, 2026

    @rbuergi
    Contributor

    Two loops this thread left open, and one of them falsifies its surviving sub-hypothesis

    Grouped as part of the area:mesh timeout cluster. Nothing here changes the disposition — this stays open, gated on #4928 — but three facts are derivable from what is already on the thread and no comment states them.

    1. The EvictForPath sub-hypothesis is falsified by the thread's own later readings

    The 2026-09-14 21:44Z comment named a mechanism that predicts the hot-path concentration: Workspace.EvictForPath fires on every change-feed event and evicts unconditionally, including the mirror the writer just used, so every hot write re-hydrates a brand-new mirror inside the 30 s bound — and it predicted census branch one for the next occurrence. It was offered as "falsifiable in one line once a replica carrying 48a3bee is rolled".

    That falsification has now happened three times and nobody closed the loop:

    So branch one was read on images carrying the fix that was predicted to remove its cause. EvictForPath is not what produces it. That eliminates the one competing hypothesis this thread had, and leaves the ghost/stale query positive as the only mechanism still standing.

    2. The 2026-09-18 10:25Z premise is superseded within the same day

    That comment states memex-cloud carries none of #4342/#4428/#4468 and is still on c84c6c05. The 17:04:23Z sample later that day, on a new pod (fb6488b5f-x7bv5), prints the #4342 census text verbatim — so memex-cloud rolled onto a #4342-carrying image between those two timestamps, and the "do not read the silence as a fix, no pod runs it" reasoning does not cover the samples that followed.

    3. The Trail: instrument's silence has a second, better explanation

    The 2026-09-16 09:01Z comment attributes the unread RequestFateLedger trail to "no portal runs 141e5fdc". But no sample after 2026-09-15T18:56:54Z is the self-addressed shape (b) — every later one is shape (a), the BaseStateTimeoutException. The trail instrument #4468 shipped exists to discriminate shape (b)'s intake-refusal-versus-detached-chain fork. It has had no shape-(b) occurrence to print on, which is a different reason for its silence than image lag, and it means the (a)-vs-(b) question the thread lists as open may no longer be reachable from production at all.

    Disposition

    Leave open, gated on #4928. The remedy the thread converged on — the caller must not decide create-vs-update from an eventually-consistent index positive — is now also the platform's written rule (AGENTS.md names this issue by number as the fallback that rule forbids), and it cannot be implemented while CreateOrUpdateNodeRequest cannot express a fold. Naming the gap is the correct state; I did not route TrackActivity through the upsert, because doing so loses the counter increment and that is exactly what #4928 is.

    sev:M stands.

    On its relationship to #5115

    Kept separate, and the 2026-09-21 19:52Z reasoning on #5115 is right: this ticket is a diagnosed root, #5115 is an undiagnosed symptom family over the same log site, and folding the family into the root buries whichever of the two is wrong. Same log site + different diagnostic state ⇒ keep both. Recorded on #5115 too, with the fingerprint-lineage evidence that they ARE the same site (#5115 inherited 7473a637daf1e169, which is this ticket's fingerprint).

    What I did NOT establish

    Grouping method committed as Doc/Architecture/OneLogSiteManyTerminals (PR #5170).

  21. rbuergi commented on Sep 22, 2026

    @rbuergi
    Contributor

    Grouping verdict: NOT the same root as the MeshNodeHubFactory pair (#5008 / #2231) — and the blocker this thread has been gated on since 2026-09-19 is GONE. The remedy it converged on is in main. Full verdict: #5008 (comment)

    This ticket was put to me as possibly one root with #5008, #2231 and #4597. It is not: that cluster is a NodeType resolution defect at the activation/write boundary; this one is a caller deciding create-vs-update from an eventually-consistent index. Nothing in either touches the other.

    🚨 The gate is lifted and the caller has moved

    The 2026-09-19 19:22Z comment localised this to one line and filed the framework gap as #4928, stating the reason it could not simply be fixed: "a delegate cannot cross the wire." #4970 then designed the declarative alternative. Both halves have landed.

    CreateOrUpdateNodeRequest.Folds exists, with ContentFold / ContentFolds / WithFolds<T> and the rules Sum / Max / Min / KeepExisting (src/MeshWeaver.Mesh.Contract/ContentFold.cs), applied owner-side inside the Update lambda the upsert already runs (MeshExtensions.cs:~6398). And MeshWeaver.Graph/MeshNodeExtensions.cs no longer branches on the query index at all — HandleTrackActivity now issues one upsert (commit 2b514860dc, "Fix activity tracking with owner-side upsert folds"):

    var request = new CreateOrUpdateNodeRequest(saveNode)
        .WithFolds<UserActivityRecord>(jsonOptions, folds => folds
            .Sum(r => r.AccessCount, 1)
            .KeepExisting(r => r.FirstAccessedAt)
            .Max(r => r.LastAccessedAt, now)) with { RequestedBy = callerCtx?.ObjectId };

    The three folds are exactly the three things FoldOntoLive did, in the order the 2026-09-20 11:35Z comment tabulated them — AccessCount sum, FirstAccessedAt keep-live, LastAccessedAt take-newer. That comment's objection ("whatever lands for #4928 has to carry more than 'increment'") is answered rather than sidestepped. The code carries this issue by number: "The query index can retain a positive row while its node has no live base; using that row to choose stream.Update selected the unsafe update path implicated in #1174."

    So this thread's own acceptance criterion — "MeshNodeExtensions.cs:379-392 no longer chooses its write from a query result" — is met, and there are no lines 379-392 of that shape left to point at.

    What that does NOT settle, stated so nobody reads this as done

    • It is not verified live. The merge landed today; no portal is running it. The 2026-09-19 10:34Z comment's own reasoning applies unchanged — a silence after a roll is only evidence if the instrument that would break it is working, and that comment established the incident pipeline can be dark for hours.
    • It does not close the other three causes. BaseStateTimeoutException cannot distinguish a cold data source, a still-activating hub and an initial read yielding nothing. The 19:22Z comment's honest-limits section stands: the ghost/stale-positive is a mechanism the code can produce deterministically, not a proven cause of any given occurrence.
    • It does not change the site-only fingerprint, so this ticket stays reopenable by any ActivityTracking error.

    I have not closed this, changed its labels, or touched its state — the remaining work is a post-roll reading, which is not mine to take. Recording the code state so the next reader does not re-derive a blocker that no longer exists.

  22. rbuergi commented on Sep 23, 2026

    @rbuergi
    Contributor

    Post-roll status 2026-09-23: #5187 is live on both portals, and the new path has one timeout sample. It is on #5230

    • Deployed. Track activity with owner-side upsert folds #5187 (ad17f6e5c9) is contained in both running builds: memex.systemorph.com runs 3da3423c4b and memex.meshweaver.cloud runs 39f49494eb, both checked with git merge-base --is-ancestor.
    • The query-decided create-vs-update this issue was localised to is gone from HandleTrackActivity. Activity tracking now issues one CreateOrUpdateNodeRequest with owner-side folds.
    • One sample of the NEW path timing out exists: Activity-tracking CreateOrUpdateNodeRequest reaches target hub handler but never returns a response (60s timeout) #5230, memex-cloud, 2026-09-22 11:22:28Z. Its trail reaches HANDLER_ENTER → HANDLER_EXI… on portal/nodeops-… and then goes silent for 60 s. It is not this issue's shape: the request is a CreateOrUpdateNodeRequest, not a self-addressed CreateNodeRequest, and nothing decides create-vs-update from the index. The triage there shows every leg of the upsert's detached work answering except the existence read, which has no own bound. The truncated trail hides which leg it was.

    Not closing: this issue's own verification is a clean window after the roll on the instrument that would show the old shape, and I could not take a Logs read (the control instance's MCP answers 503). #5230 carries the new shape separately.

  23. rbuergi commented on Sep 23, 2026

    @rbuergi
    Contributor

    Closing: the localised defect is fixed and deployed, and the code path it described no longer exists

    • Fix: Track activity with owner-side upsert folds #5187 (ad17f6e5c9). HandleTrackActivity no longer decides create-vs-update from the query index. It issues one CreateOrUpdateNodeRequest with owner-side folds (Sum AccessCount, KeepExisting FirstAccessedAt, Max LastAccessedAt). Existence is decided by the owner's persistence read, never by a query positive.
    • Deployed on both portals: memex.meshweaver.cloud serves 9a61fed964, and memex.systemorph.com serves 39f49494eb (/api/version, 2026-09-23T20:15Z). git merge-base --is-ancestor ad17f6e5c9 … is true for both.
    • The old shapes cannot recur. Neither shape can be produced by current code: the bare TimeoutException: Update aborted … from a query-chosen stream.Update, nor a self-addressed CreateNodeRequest from TrackActivity. The self-addressed shape (b) has had no sample since 2026-09-15.

    What remains is a different terminal, tracked where it belongs:

    A new ActivityTracking error reopens by fingerprint on its own ticket, not here.

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

    area:meshCore subsystem: the mesh - nodes, partitions, addressing, activationbugSomething isn't workingfeature:activity-trackingFeature: activity trackingsev:MMedium - secondary path broken, or easy workaround

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions