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

MeshCatalog MoveNode: copy leg refuses a rename off a whitespace path — storage lists the node the caller-scoped subtree query does not return

Closed
#7,542 3 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

A pull request for this has already been merged.

  • #7627 by @rbuergi — merged

Assessment

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

Research direction

Start with HandleMoveNodeRequest and HandleCopyNodeRequest, then read the Moving Nodes design documentation and compare the caller scoped subtree query with IStorageAdapter.ListDescendantPaths at the RequireComplete refusal branch. Check issue #6310 for the prior whitespace path incident and #4061 for the access fold case. Done means identifying which cause explains the mismatch and confirming that the same move can complete safely.

Written by the indexing model from the issue text.

Description

bug sev:M

Observed

Two MoveNode operations on the memex portal failed in their copy leg with Copy reached no verdict under MeshWeaver.Mesh.Services.IMeshCatalog. The concrete case: renaming {path} Rubin to {path} — a rename whose purpose is to remove the space from the leaf segment. The refusal states the source is stored — i.e. IStorageAdapter.ListDescendantPaths listed it in the authoritative store inventory — but the subtree query under the caller did not return it yet. The completeness comparison in the copy leg therefore could not establish a verdict, the move answered Unavailable, and by the operation's own account nothing was copied and nothing was removed at the source — non-destructive, retryable.

This is the two-surface comparison documented in Moving Nodes: HandleMoveNodeRequest / HandleCopyNodeRequest in {path} compare the RLS-filtered content query path:{source} scope:subtree (what the caller may carry) against ListDescendantPaths(source) (what storage holds), and refuse rather than relocate part of a subtree. The doc's own rule — "an unresolved viewer, a query error, or an incomplete first snapshot is a refusal, not proof that the source is absent" — names exactly the three things this incident cannot yet tell apart.

Two cross-references worth an engineer's attention:

  • This is a recurrence, not a first sighting. The prior production instance of this same log site (same site fold) was filed as {path}#6310 on 2026-10-13 (memex-cloud): source OIB/ {path}, same Copy reached no verdict refusal. In both instances the source path contains a space. That ticket left open whether the space was in the stored path or a log artifact; this instance settles it for its own case — the target path LicenseEmailFRubin has no space, so the source path verifiably does.
  • The fingerprint masker itself splits these paths at the space: the normalized template renders the source as {path} Rubin here and {id}/ {path} in #6310's incident — an independent hint that the platform's text tooling tokenizes these paths on whitespace.

Where and when

Two occurrences ~2 seconds apart on a single memex pod, both the same {path} pair — reads as one failed rename plus an immediate identical retry. Same shape and cadence as the #6310 incident (two attempts, seconds apart, one pod, one node).

Impact

Judged from the numbers: one node, one namespace, one pod, non-destructive failure with an explicit retry path — the rename of this node is blocked while the two read surfaces disagree. The broader risk is conditional on cause: if the whitespace hypothesis below holds, every node whose path contains a space would be unmovable, and the rename that would remove the space is itself the operation being refused — that would be a user-visible block with no in-product workaround. Not established beyond these two instances.

Not established

  • The cause — projection lag, an access fold, and a whitespace parsing divergence all fit the two samples.
  • Whether the move eventually succeeded. The memex / sharepointconnector state is not readable from the instance this was triaged on (searched, nothing returned), so I could not check where the node sits now.
  • The status and outcome of MeshWeaver#6310 — whether that issue is still open, and whether anything was done between 2026-10-13 and today. This ticket may be a duplicate of it; a human can merge or close in seconds.
  • Whether other nodes with whitespace paths have been moved successfully — this fingerprint covers one log site, variants: 1.

Candidate causes and the reading that separates them

  1. Incomplete first snapshot / projection lag. The node was created or renamed into the space path shortly before the attempt; storage listed it while the caller-scoped query projection had not ingested it. Predicts: a retry succeeds after the projection catches up, and the failure correlates with a write to the path in the preceding seconds. Separating reading: retry the same move after a delay, or read the node's lastModified — a stamp moments before the refusal supports this; an identical failure hours later excludes it.
  2. Access fold (RLS). The mover's identity cannot see the subtree through the query surface while the unfiltered ListDescendantPaths still lists it — the same class as the {path} refusals under {path} (MeshWeaver#4061). Predicts: the refusal is stable across retries and identical for any identity without the grant. Separating reading: the same subtree query issued as the mover — if it returns nothing while the mover demonstrably passed the move's Delete pre-flight, the gap is on the read side.
  3. Whitespace path parsing divergence. The query surface (query parser or path matcher) splits, trims or tokenizes segments on whitespace, so a stored path with a space inside a segment is not matched by a subtree prefix query that names it, while the storage adapter's raw prefix enumeration matches it byte-for-byte. Predicts: the refusal is deterministic and permanent for exactly these paths — and both known production instances of this refusal satisfy the predicate (here the move was precisely a de-spacing rename; #6310's source also carried a space). Separating reading: issue path:{path} Rubin scope:subtree (with the space) and the spaceless variant as the same identity — divergent answers isolate the parsing seam; also check whether any node with a whitespace segment has ever been moved successfully.

Where to look

  • HandleMoveNodeRequest / HandleCopyNodeRequest in {path} — the RequireComplete comparison between the caller-scoped subtree query and IStorageAdapter.ListDescendantPaths, and the reached no verdict refusal branch.
  • Moving Nodes — the design of the two-surface comparison and the refusal contract; note both concrete instances of the refusal now involve whitespace paths.
  • {path}#6310 — the prior instance at the same log site (memex-cloud, 2026-10-13); likely the same defect, and the dedupe decision belongs to a human.
  • {path}#4061 — the nearest known access-fold refusal class, if cause 2 is pursued.

Evidence
Fingerprint b152647cd2f6f86d
Category MeshWeaver.Mesh.Services.IMeshCatalog
Severity Error
Namespace memex 2 occurrence(s), 2026-10-29 07:20:02Z → 2026-10-29 07:20:04Z; pods memex-portal-deployment-769cdb4c77-flkck
Occurrences 2
First seen 2026-10-29 07:20:02Z
Last seen 2026-10-29 07:20:04Z
Routing not determined — no configured route matches the category MeshWeaver.Mesh.Services.IMeshCatalog. 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-29 07:20:02Z memex-portal-deployment-769cdb4c77-flkck fail: MeshWeaver.Mesh.Services.IMeshCatalog[0]
      [MoveNode] {path} Rubin -> {path} failed in its copy leg (Unavailable): Copy reached no verdict: '{path} Rubin' is stored, but the subtree query under the caller did not return it yet. Nothing was copied; the copy may be retried.
2026-10-29 07:20:04Z memex-portal-deployment-769cdb4c77-flkck fail: MeshWeaver.Mesh.Services.IMeshCatalog[0]
      [MoveNode] {path} Rubin -> {path} failed in its copy leg (Unavailable): Copy reached no verdict: '{path} Rubin' is stored, but the subtree query under the caller did not return it yet. Nothing was copied; the copy may be retried.

This log site's previous ticket, https://github.com/Systemorph/MeshWeaver/issues/6951, was closed about a different fingerprint, and this fault fired after that close. It is left closed: an occurrence of this fingerprint is no evidence that the fault it was closed for came back. This issue now tracks the log site, and later fingerprints of it fold in here.

Opened automatically from Admin/_LogIncident/b152647cd2f6f86d. Recurrences are folded into this issue rather than opening new ones.
It also stands for the whole log site a5d75353732af2db: 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 37m
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.