Skip to content

fix(paths): structurally resolve home dir to prevent Windows path bugs#12125

Merged
sebslight merged 2 commits intoopenclaw:mainfrom
mcaxtr:fix/12119-windows-homedir-resolve
Feb 9, 2026
Merged

fix(paths): structurally resolve home dir to prevent Windows path bugs#12125
sebslight merged 2 commits intoopenclaw:mainfrom
mcaxtr:fix/12119-windows-homedir-resolve

Conversation

@mcaxtr
Copy link
Contributor

@mcaxtr mcaxtr commented Feb 8, 2026

Fixes #12119

Problem

resolveEffectiveHomeDir() returned raw env-var values (e.g. OPENCLAW_HOME="/custom/home") without calling path.resolve(). On POSIX this is harmless, but on Windows path.join("/custom/home", ".openclaw") produces \custom\home\.openclaw (missing the drive letter), breaking STATE_DIR and CONFIG_PATH derivation.

Additionally, shortenMeta() in tool-meta.ts used indexOf(":") to split file:line patterns (e.g. file.txt:12), but this conflicts with Windows drive letters (C:\...) where the colon appears at index 1.

Both issues were introduced/exposed by #12091 which added OPENCLAW_HOME support.

Fix

  1. Structural gate (home-dir.ts): Extract the raw lookup logic into a private resolveRawHomeDir() and gate the public resolveEffectiveHomeDir() through a single path.resolve() exit point. This makes it structurally impossible for unresolved paths to escape, regardless of how many return paths exist. Future developers can add new env-var sources without remembering path.resolve().

  2. Simplify resolveRequiredHomeDir: Remove the now-redundant path.resolve() wrapper — only the process.cwd() fallback needs it.

  3. Fix shortenMeta (tool-meta.ts): Remove the colon-based split that conflicts with Windows drive letters. shortenHomeInString() already handles file:line patterns correctly via split(home).join(prefix), so the colon split was both unnecessary and harmful.

  4. Tests: Update assertions across all affected files to use path.resolve() in expected values and input strings so they match the now-correct resolved output on both Unix and Windows.

Test plan

  • All 8 home-dir.test.ts tests pass
  • All 6 tool-meta.test.ts tests pass
  • All 25 utils.test.ts tests pass
  • All 10 agent-scope.test.ts tests pass
  • All 9 paths.test.ts tests pass
  • All 19 config.nix-integration-u3-u5-u9.test.ts tests pass
  • All 4 workspace.test.ts tests pass
  • All 19 profile.test.ts tests pass
  • All 29 session-utils.fs.test.ts tests pass
  • pnpm build && pnpm check clean
  • Windows CI (checks-windows) passes

@openclaw-barnacle openclaw-barnacle bot added the agents Agent runtime and tooling label Feb 8, 2026
@mcaxtr
Copy link
Contributor Author

mcaxtr commented Feb 8, 2026

Hey @sebslight, this is a follow-up to your #12091 work. On Windows, resolveEffectiveHomeDir returned raw env-var strings — so path.join("/custom/home", ".openclaw") produced \custom\home\.openclaw (no drive letter), breaking state/config path derivation.

The fix has two parts:

  1. Structural gate in home-dir.ts: Extracted the lookup logic into a private resolveRawHomeDir() and made the public resolveEffectiveHomeDir() a thin wrapper that calls path.resolve() at the single exit point. This way future env-var sources get resolution for free.

  2. shortenMeta fix in tool-meta.ts: The resolved paths exposed a pre-existing bug — indexOf(":") for file:line splitting (file.txt:12) matched the Windows drive letter (C:\...) first. Removed the colon split since shortenHomeInString already handles file:line patterns correctly via split(home).join(prefix).

Would love your thoughts when you have a moment!

@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime cli CLI command changes labels Feb 8, 2026
@mcaxtr mcaxtr force-pushed the fix/12119-windows-homedir-resolve branch 3 times, most recently from 4ab6cd8 to 4be3c50 Compare February 8, 2026 23:48
@mcaxtr mcaxtr changed the title fix(paths): resolve home dir to fully qualified path on Windows fix(paths): structurally resolve home dir to prevent Windows path bugs Feb 9, 2026
@sebslight sebslight self-assigned this Feb 9, 2026
@sebslight sebslight force-pushed the fix/12119-windows-homedir-resolve branch from 4be3c50 to d586252 Compare February 9, 2026 01:01
mcaxtr and others added 2 commits February 8, 2026 20:02
Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119
@sebslight sebslight force-pushed the fix/12119-windows-homedir-resolve branch from d586252 to b04330e Compare February 9, 2026 01:04
@sebslight sebslight merged commit 456bd58 into openclaw:main Feb 9, 2026
23 checks passed
@sebslight
Copy link
Member

Merged via squash.

Thanks @mcaxtr!

akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 9, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
zendizmo pushed a commit to zendizmo/openclaw that referenced this pull request Feb 9, 2026
openclaw#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119

* fix(changelog): add paths Windows fix entry (openclaw#12125)

---------

Co-authored-by: Sebastian <[email protected]>
yeboster pushed a commit to yeboster/openclaw that referenced this pull request Feb 9, 2026
openclaw#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119

* fix(changelog): add paths Windows fix entry (openclaw#12125)

---------

Co-authored-by: Sebastian <[email protected]>
Ethermious pushed a commit to Ethermious/openclaw that referenced this pull request Feb 9, 2026
openclaw#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119

* fix(changelog): add paths Windows fix entry (openclaw#12125)

---------

Co-authored-by: Sebastian <[email protected]>
lucasmpramos pushed a commit to butley/openclaw that referenced this pull request Feb 10, 2026
openclaw#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119

* fix(changelog): add paths Windows fix entry (openclaw#12125)

---------

Co-authored-by: Sebastian <[email protected]>
yeboster pushed a commit to yeboster/openclaw that referenced this pull request Feb 13, 2026
openclaw#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119

* fix(changelog): add paths Windows fix entry (openclaw#12125)

---------

Co-authored-by: Sebastian <[email protected]>
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 13, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
skyhawk14 pushed a commit to skyhawk14/openclaw that referenced this pull request Feb 13, 2026
openclaw#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes openclaw#12119

* fix(changelog): add paths Windows fix entry (openclaw#12125)

---------

Co-authored-by: Sebastian <[email protected]>
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 14, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
mbelinky pushed a commit that referenced this pull request Feb 14, 2026
#12125)

* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes #12119

* fix(changelog): add paths Windows fix entry (#12125)

---------

Co-authored-by: Sebastian <[email protected]>
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 14, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 15, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 16, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 18, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
akoscz added a commit to akoscz/openclaw that referenced this pull request Feb 20, 2026
resolveDefaultConfigCandidates returns resolved paths (with drive letter
on Windows) after upstream openclaw#12125. The test used raw path.join with a
Unix-style home, missing the drive prefix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling cli CLI command changes gateway Gateway runtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: config nix-integration tests fail on Windows CI (missing drive letter in path.resolve)

2 participants

Comments