Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

SaveMeshNodeHandler: store flushes of an edited feedback node refused by a concurrent subtree deletion, leaving two versions pending

Open
#6,953 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
csharp
Domain
backend, databases

Research direction

Start with MeshWeaver.Graph.SaveMeshNodeHandler, then inspect SubtreeDeletionGuardStorageAdapter and RecentlyDeletedRegistry.BeginSubtreeDeletion. Read /Doc/Architecture/RecursiveDeleteDrain and compare the write-conflict traces with the delete start and Loki [DeleteNode] logs for the named pod. Determine whether the refusal is expected, whether the delete aborted, and whether versions 3–4 were later persisted; the issue does not identify a definite code change.

Written by the indexing model from the issue text.

Description

bug sev:L

Observed

Two consecutive store writes issued by the persistence sampler's SaveMeshNodeRequest handler (MeshWeaver.Graph.SaveMeshNodeHandler) for rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub — versions 3 and 4 — were refused with MeshWeaver.Mesh.SubtreeDeletionInFlightException: a recursive deletion of exactly that node's subtree was open when the flushes were issued. The handler answered that the state "is not durable" and stays pending, to be re-attempted by the next save or the hub's dispose flush. At the time of this report the node's durable history in the store ends at version 2 (written 2026-10-18T07:56:13.87Z by system-security), while the mesh node sits at version 4 — the two refused writes had not landed.

Where and when

One pod, one node, one burst of two refusals 200 ms apart. Both versions were merged into the in-memory node within the second before the refusals (version 4's merge is stamped 07:56:14.73Z, also by system-security, the platform's automated identity), so edits to the node and a delete of the same node were concurrent within roughly one second. The node is a user feedback item in rbuergi's personal space; the writer of the refused flushes was not the node's owner.

Impact

Bounded to one node. At most versions 3–4 of this one feedback item are non-durable until a later save or the hub's dispose flush; if the in-flight delete completed, the node is gone and the pending writes are moot; if the delete aborted, they flush on the next save, and until then a pod restart loses them. No user-visible failure was observed; whether the writer's own answer acknowledged durability is not visible from this log site.

Not established

  • Who issued the recursive delete of the node, and whether it completed, aborted, or was still running when the incident was opened. At 07:57Z the node still existed at version 4 with no Redirect replacement (sibling feedback items that were submitted exist today as Redirect nodes with a copy under Feedback/_Submissions; no copy of this item was found there), so the delete had not completed as of that reading.
  • Whether the two pending writes later landed.
  • Whether the in-memory merges of versions 3–4 happened before or after the deletion scope opened. The refusals only prove the flushes were issued after the scope opened; the merges could precede it, because the sampler's flush lags the merge.
  • Whether a refusal at this log site is an expected, designed record of the guard doing its job or a defect-shaped symptom; the architecture documentation names this handler as one of the three write routes that must honour the tombstone, but does not state that reaching this refusal in production is expected.
  • Whether this race has occurred at other paths; this is the only recorded burst at this log site.

Candidate causes and the reading that separates them

  1. Designed refusal in a benign race. A recursive delete of the node opened while the sampler flushed the node's two newest versions; the guard refused at admission and the handler kept them pending. Predicts: the delete completed and the node is now gone or replaced by a Redirect, with a copy under Feedback/_Submissions. Reading: the node's current state and the Feedback/_Submissions partition settle it.
  2. An automated flow racing itself. The edits (versions 3–4, by system-security) and the delete of the same node fall within about a second of each other and may be two steps of one pipeline — patch, then delete, the submission flow's shape. Predicts: the delete's caller and the editor are the same actor. Reading: the delete's Ops action record or the hub's activity traces for this path name the caller.
  3. The hub merged edits while the deletion scope was open. The subtree-deletion scope is documented to refuse every in-process write at or under the root; if the merges of versions 3–4 happened after the scope opened, a node under deletion mutated in memory while its durability was refused. Predicts: the merges' timestamps fall after the delete's scope open (RecentlyDeletedRegistry.BeginSubtreeDeletion). Reading: the {path}/_Activity/write-conflict-{version} traces versus the delete's start timestamp on the pod. This is the only candidate that implies a code-level gap; the other readings would rule it out.
  4. The delete aborted after refusing the writes. The node then remains with non-durable versions 3–4 until the next save. Predicts: the node still exists, the store holds version 2, and no successful [DeleteNode] line exists for the path. Reading: Loki [DeleteNode] lines for the path on pod memex-portal-deployment-7bc8cb4d47-npczw from 07:56:14Z onward.

Causes 1 and 2 are not mutually exclusive. If the readings under 4 show the delete aborted and the two versions were never re-flushed, this item's severity should be re-ruled upward — two versions of a node silently non-durable is worse than this burst's numbers suggest.

Where to look

  • MeshWeaver.Graph.SaveMeshNodeHandler — the persistence sampler's SaveMeshNodeRequest handler, the log category of this incident.
  • SubtreeDeletionGuardStorageAdapter / RecentlyDeletedRegistry.BeginSubtreeDeletion (MeshWeaver.Mesh) — the admission-time refusal that raised the exception.
  • The Recursive-Delete Drain, section "Every write route an owner uses honours the tombstone" — names this exact handler as one of the three routes that must drop a write while the tombstone is live.
  • The node itself: rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub (current mesh version and durable history).

Duplicate check: no prior incident exists at this log site. The recorded delete-side incidents ([DeleteNode] timeouts, partial deletes) are the other side of this mechanism; this is the first write-side refusal recorded at SaveMeshNodeHandler.


Evidence
Fingerprint bcd6c007985166d0
Category MeshWeaver.Graph.SaveMeshNodeHandler
Severity Error
Exception MeshWeaver.Mesh.SubtreeDeletionInFlightException
Namespace memex
Pods memex-portal-deployment-7bc8cb4d47-npczw
Occurrences 2
First seen 2026-10-18 07:56:14Z
Last seen 2026-10-18 07:56:15Z
Routing not determined — no configured route matches the category MeshWeaver.Graph.SaveMeshNodeHandler. This repository is the configured fallback, not a finding about who owns the fault; the category names the LOGGER, which may not be the subject.
Recent log lines
2026-10-18 07:56:14Z memex-portal-deployment-7bc8cb4d47-npczw fail: MeshWeaver.Graph.SaveMeshNodeHandler[0]
      [SaveMeshNode] the store write of rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub (version=3) FAILED — the state is not durable. It stays pending: the next save or the hub's dispose flush re-attempts it.
      MeshWeaver.Mesh.SubtreeDeletionInFlightException: Cannot write 'rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub': the subtree 'rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub' is currently being deleted.
2026-10-18 07:56:15Z memex-portal-deployment-7bc8cb4d47-npczw fail: MeshWeaver.Graph.SaveMeshNodeHandler[0]
      [SaveMeshNode] the store write of rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub (version=4) FAILED — the state is not durable. It stays pending: the next save or the hub's dispose flush re-attempts it.
      MeshWeaver.Mesh.SubtreeDeletionInFlightException: Cannot write 'rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub': the subtree 'rbuergi/Feedback/20260922-meshservice-caches-a-disposed-nodeops-issuing-hub' is currently being deleted.

Opened automatically from Admin/_LogIncident/bcd6c007985166d0. Recurrences are folded into this issue rather than opening new ones.
It also stands for the whole log site dbdda86d9ba3d306: other fingerprints of this site fold in here as comments rather than opening tickets of their own.

Dominant language
C#
Stars
12
Forks
5
Avg merge
5h 53m
Merged PRs (30d)
959

Getting set up

  • No Dockerfile or Docker Compose file
  • Has a pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Systemorph/MeshWeaver

All issues in Systemorph/MeshWeaver

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.