Repository navigation
grep_search: spurious "escapes workspace boundary" on first run in a directory with no .claw/ (Windows) #3278
Description
Activity
Reproduced on Windows 11. The root cause is indeed the \?\ extended-length prefix — s::canonicalize on Windows prepends it while the boundary path from workspace config doesn't. The fix should normalize both paths by stripping \?\ before comparison (e.g. via dunce::canonicalize or a manual strip). Happy to help test a fix.
One additional observation: the race condition with .claw/ initialization suggests the boundary check runs before the workspace root is fully established. The fix likely needs two parts: (1) path normalization via dunce::canonicalize to strip the backslash-backslash-question-mark prefix on Windows, and (2) deferring the boundary check until after workspace bootstrap completes. The dunce approach alone would be a one-line fix replacing std::fs::canonicalize with dunce::canonicalize which already handles prefix stripping transparently.
Good bug report — the root cause analysis is spot on. The \?\ extended-length prefix mismatch is a classic Windows path normalization issue: canonicalize() returns the extended-length form while the workspace boundary check stores the plain form, so the containment comparison fails on first run before .claw/ exists and triggers canonicalization of the stored boundary. The fix should normalize both sides to the same representation (either both with \?\ stripped or both with it applied) before the substring/prefix containment check. The dunce::simplified() or equivalent from the path-clean crate would handle this cleanly.
Reproduced on Windows. The issue is that workspace boundary validation fires before .claw/ initialization on first-ever run. Fix should be straightforward: either defer the boundary check or bootstrap .claw/ first. Happy to submit a PR if no one is on it.
I can reproduce this on Win11 — it seems to be a timing issue where the workspace boundary check fires before the .claw/ directory is first initialized. A possible fix would be to defer the boundary validation until after the first successful workspace detection, or to special-case the " no .claw/ exists yet\ scenario as a non-boundary-violating state. Happy to test a patch if someone puts one up.
I can prepare a focused fix for the Windows extended-path boundary mismatch, with regression coverage for a first run without .claw/, if no one is actively implementing it. @1716775457damn, are you planning to submit a PR? If not, I’ll proceed and keep the change limited to path normalization/initialization behavior.
Confirmed — PR #3286 addresses the root cause (path normalization for \\?\ prefix). Once that merges, this can be closed. Thanks @SulimanAbdulrazzaq for the fix!
This matches what I see on Windows too: the reported "escaping" path and the boundary path are the same directory, differing only by the \?\ extended-length prefix. The initialization-order aspect (works once .claw/ exists) is also consistent with the boundary check comparing a canonicalized path against a non-normalized one. Note that #3286 already addresses exactly this — it normalizes \?\ extended-length and UNC prefix variants before the boundary comparison, with regression tests. This issue can be closed once that PR lands.
Re-tested on Windows 11 (build 26200) with current
main: the failure still reproduces on the first run in a fresh directory, so I think there are two distinct defects here that need separate fixes rather than one.- Prefix mismatch —
std::fs::canonicalizereturns the\\?\-prefixed form while the workspace boundary stored in config stays plain, so the containment check compares two representations of the same path.dunce::canonicalize(ordunce::simplifiedapplied to the already-canonicalized path) normalizes both sides and fixes the comparison itself. - Bootstrap ordering — even with (1) in place, the boundary check appears to run before
.claw/is written. That matches the observed data: 2/3 fresh dirs failed, and the one that passed already had.claw/sessions/*.jsonlflushed by the timegrep_searchran. Normalizing paths alone does not guarantee the root is established, so the check should be deferred until workspace init completes, otherwise the fresh-directory case can remain flaky.
#3286 looks like it targets (1). Before closing this, it would be worth confirming whether it also covers (2) — otherwise the first-run-in-a-fresh-dir case may still fail intermittently even with the prefix fix merged.
Happy to re-run the repro matrix against a candidate branch if that helps.
- Prefix mismatch —
Summary
On Windows, the first
grep_searchin a working directory that does not yet contain a.claw/directory fails with a workspace-boundary error. The reported "escaping" path and the boundary path are the same path, differing only by the\?\extended-length prefix — which suggests the boundary check compares a plain path against a canonicalized/extended path without normalizing the prefix first.Once
.claw/exists in that directory, subsequentgrep_searchcalls succeed. So this reads as an initialization-order race rather than a permanent failure.Error
Note both sides are
C:\tmp\clawpath\normaldir; only the prefix differs.Reproduction
Observed
.claw/present beforehandgrep_searchReproduced on 2 of 3 fresh directories; 0 of 3 already-initialized directories. The one fresh directory that succeeded had
.claw/sessions/*.jsonlalready flushed by the time grep ran, which is consistent with a race between workspace initialization and the tool's boundary check.Expected
grep_searchshould resolve/normalize both paths (strip or apply the\?\prefix consistently) before the containment comparison, and should not depend on.claw/already existing.Impact
read_fileworks in the same directory wheregrep_searchfails, so the failure is partial and easy to misread as a model/tool-calling problem rather than a harness bug — it cost us some misdiagnosis while evaluating local models.Environment
v0.1.3(git4ea31c1bc91c), built from sourcerustc/cargo1.97.1, MSVC (VS Build Tools 2019):1234)Workaround
Run any command that initializes
.claw/in the directory first, thengrep_searchworks.