Skip to content

fix(infra): tolerate deleted cwd across startup, PATH, home-dir, and TUI [AI-assisted]#93636

Merged
steipete merged 1 commit into
openclaw:mainfrom
ml12580:fix/vuln-73676
Jul 5, 2026
Merged

fix(infra): tolerate deleted cwd across startup, PATH, home-dir, and TUI [AI-assisted]#93636
steipete merged 1 commit into
openclaw:mainfrom
ml12580:fix/vuln-73676

Conversation

@ml12580

@ml12580 ml12580 commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Closes #73676. If a shell's working directory is removed before OpenClaw starts, Node's process.cwd() throws ENOENT: uv_cwd. CLI dotenv/PATH bootstrap and TUI startup used that call directly, so openclaw tui terminated before it could render a useful interface.

Why This Change Was Made

Introduce one small nullable-CWD primitive, then keep the decision at each owner boundary:

  • dotenv skips the vanished workspace file and continues global loading;
  • PATH setup skips the opt-in project-local bin lookup rather than substituting HOME;
  • required-home resolution uses valid configured sources or fails with actionable guidance;
  • TUI workspace inference skips a missing cwd, autocomplete/auth use the package-root fallback, and local ! commands refuse instead of silently running somewhere else.

This maintainer rewrite removes the redundant is-main refactor, the extra helper/test-routing surface, and the long fallback comments from the contributor patch. Normal cwd-present behavior is unchanged.

User Impact

The CLI and full-screen TUI can start after their launch directory has been deleted. Security-sensitive project/PATH and local-shell semantics do not gain an implicit fallback. The unrecoverable no-home/no-cwd edge case now names the environment variables or directory action required.

Evidence

  • Blacksmith Testbox tbx_01kwsmjrh13za4ghjn0kcrhfjt, run 28748684029: 147 focused boundary/dotenv/TUI tests passed on the final rebased source.
  • Blacksmith Testbox tbx_01kwskqhr1tm4d5r3g5vwh7ce8, run 28748286393: corepack pnpm check:changed passed for the exact 14-file core/coreTests scope, including full core lint/typecheck/guards.
  • Same Testbox: built OpenClaw, started CLI and full-screen TUI in tmux directories removed before Node launch, observed version plus gateway disconnected, and observed no uv_cwd; command exited 0.
  • Same Testbox: fake/local/real-Gateway PTY lane passed 24/24.
  • Fresh post-rebase autoreview: no accepted/actionable findings; correctness confidence 0.94.
  • git diff --check passed.

Release note: Fixed CLI and TUI startup crashes when the current working directory is deleted, while preserving project-local PATH and local-shell safety boundaries.

@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes size: S triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 16, 2026
@vincentkoc vincentkoc self-assigned this Jun 16, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Maintainer review found this does not yet fix the reported deleted-cwd TUI path. runTui and tui-local-shell still call bare process.cwd(), so openclaw tui can still crash after startup. Mapping a missing cwd to HOME also changes project-local PATH trust semantics by treating $HOME/node_modules/.bin as the deleted project path; dotenv, PATH, required-home, and TUI need caller-specific fallback behavior instead of one generic HOME fallback. PR #93034 is the stronger repair base because it uses nullable cwd handling, skips project-local PATH lookup, and covers TUI, though it still needs rebase/conflict repair and removal of its tmpdir required-home fallback. Keeping this PR open rather than landing the current incomplete shape.

ml12580 added a commit to ml12580/openclaw that referenced this pull request Jun 17, 2026
Rework per maintainer review on openclaw#93636: drop the generic safeCwd()->HOME
fallback in favor of nullable cwd handling (tryProcessCwd), with each
caller choosing its own behavior:
- dotenv: skip workspace .env (already done)
- PATH: skip project-local bin lookup when cwd is null (was wrongly
  remapping to $HOME/node_modules/.bin, changing PATH trust semantics)
- required-home: fall back to the running Node binary dir (not os.tmpdir
  shared-temp, not a generic HOME that is already empty in this branch)
- TUI: cover runTui, resolveLocalAuthSpawnCwd, and
  resolveInitialTuiAgentId (previously unguarded bare process.cwd())
- tui-local-shell: fall back to os.homedir() for !cmd spawn cwd

Adopts the nullable-cwd design from PR openclaw#93034 (the endorsed repair base),
diverging on the required-home fallback (execPath dir instead of tmpdir).
Closes openclaw#73676.
@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: M and removed size: S labels Jun 17, 2026
@ml12580

ml12580 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@vincentkoc Thanks for the review — reworked this PR to address all four points. Pushed in 0fd104e.

1. TUI coveragerunTui, resolveLocalAuthSpawnCwd, resolveInitialTuiAgentId, and the tui-local-shell !cmd runner no longer call bare process.cwd(). runTui resolves a nullable launchCwd once; agent workspace inference is skipped when cwd is gone, and the auth-spawn / autocomplete / session-cwd paths fall back to the CLI wrapper's own directory. tui-local-shell falls back to os.homedir() for the spawn cwd.

2. Nullable cwd instead of one generic HOME fallback — dropped safeCwd()→HOME. Added src/infra/safe-cwd.ts with tryProcessCwd(): string | null + resolveProcessCwdOrFallback(fallback). Each caller now picks its own behavior:

  • dotenv (cli/dotenv, gateway-dispatch-dotenv, run-main, infra/dotenv): skip workspace .env, global still loads
  • PATH (path-env): if (allowProjectLocalBin && cwd)skip project-local bin when cwd is null, so $HOME/node_modules/.bin is never treated as the deleted project path
  • required-home: fall back to path.dirname(process.execPath) (see WA business, groups & office hours  #3)
  • TUI: wrapper dir; local shell: os.homedir()

3. required-home fallback — deliberately not os.tmpdir() and not os.homedir() — that branch only runs when every home source (OPENCLAW_HOME/HOME/USERPROFILE/Termux/os.homedir()) is unavailable, so os.homedir() is already empty/throwing there and path.resolve(os.homedir()) reaches back into process.cwd() and crashes on a deleted cwd. os.tmpdir() is guaranteed non-empty but shared-temp state writes are a symlink/pre-create surface (the #74994 concern). I fell back to the running Node binary's directory: always non-empty, points at a real existing dir, not shared. Open to a different choice if you'd prefer something else here.

4. Alignment with #93034 — adopted its nullable-cwd design, tryProcessCwd naming, PATH-skip, and TUI changes (and went a bit further by also hardening tui-local-shell, which #93034 didn't touch). Deliberate divergence is only the required-home fallback (#93034 uses os.tmpdir(), which you flagged for removal).

Verification: oxfmt/tsgo/oxlint clean; safe-cwd/home-dir/dotenv/run-main/tui/tui-local-shell tests pass (incl. new deleted-cwd regression tests for each caller). path-env has 2 pre-existing Linuxbrew/macOS failures on main, unrelated to this change.

Would appreciate your read on the required-home fallback choice.

@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 17, 2026
@ml12580 ml12580 changed the title fix(infra): guard all startup process.cwd() callers against deleted CWD [AI-assisted] fix(infra): tolerate deleted cwd across startup, PATH, home-dir, and TUI [AI-assisted] Jun 17, 2026
@openclaw-barnacle openclaw-barnacle Bot added triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 17, 2026
@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 2:59 PM ET / 18:59 UTC.

Summary
The branch adds a nullable tryProcessCwd() primitive and routes CLI dotenv, gateway dotenv, PATH bootstrap, required-home resolution, TUI agent/auth/autocomplete, and TUI local-shell handling through caller-specific deleted-cwd behavior plus regression tests.

PR surface: Source +44, Tests +96. Total +140 across 14 files.

Reproducibility: yes. from source: current main still calls bare process.cwd() in the reported CLI/TUI deleted-cwd paths, and the linked issue provides concrete openclaw tui steps. I did not run a live repro in this read-only review; the PR supplies after-fix Testbox/tmux proof.

Review metrics: 1 noteworthy metric.

  • Deleted-cwd policy surfaces: 4 caller families updated. Dotenv, PATH, required-home, and TUI/local-shell each get explicit behavior, which is the main owner-boundary question for this fix.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #73676
Summary: This PR is the strongest current candidate fix for the canonical deleted-cwd CLI/TUI startup crash; older attempts overlap but are not the current clean repair path.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] Exact-head hosted CI was still completing during this read-only review; this is a normal merge gate, not a code finding.

Maintainer options:

  1. Decide the mitigation before merge
    Land this caller-specific deleted-cwd fix after exact-head required checks pass, then close [Bug]: CLI crashes when current working directory is deleted (uv_cwd error not handled) #73676 and retire or supersede overlapping fix attempts such as fix(cli): tolerate deleted startup cwd #93034.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] No repair job is needed; there are no blocking code findings, so the remaining action is exact-head CI completion and maintainer merge handling.

Security
Cleared: No concrete security or supply-chain regression was found; the diff adds no dependencies or workflow execution and avoids unsafe PATH/local-shell retargeting.

Review details

Best possible solution:

Land this caller-specific deleted-cwd fix after exact-head required checks pass, then close #73676 and retire or supersede overlapping fix attempts such as #93034.

Do we have a high-confidence way to reproduce the issue?

Yes from source: current main still calls bare process.cwd() in the reported CLI/TUI deleted-cwd paths, and the linked issue provides concrete openclaw tui steps. I did not run a live repro in this read-only review; the PR supplies after-fix Testbox/tmux proof.

Is this the best way to solve the issue?

Yes. The caller-specific nullable-cwd shape is better than a generic HOME or temp fallback because dotenv, PATH, required-home, TUI auth/autocomplete, and local shell each preserve their own trust boundary.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c730d8f1f1bb.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body and maintainer comments include after-fix real deleted-cwd CLI/TUI Testbox/tmux proof, and GitHub shows the current-head real behavior proof check passing.
  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.

Label justifications:

  • P2: This is a normal-priority CLI/TUI crash fix with limited blast radius and a focused linked bug report.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and maintainer comments include after-fix real deleted-cwd CLI/TUI Testbox/tmux proof, and GitHub shows the current-head real behavior proof check passing.
Evidence reviewed

PR surface:

Source +44, Tests +96. Total +140 across 14 files.

View PR surface stats
Area Files Added Removed Net
Source 9 66 22 +44
Tests 5 97 1 +96
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 14 163 23 +140

What I checked:

  • Current-main crash source: Current main still uses bare process.cwd() in the reported startup/TUI paths, including TUI agent inference, autocomplete, auth spawn cwd, and local shell cwd, which matches the linked deleted-cwd report. (src/tui/tui.ts:542, c730d8f1f1bb)
  • Current-main CLI/PATH source: Current main also builds dotenv and PATH candidates from bare process.cwd(), so the PR targets actual current source paths rather than only a historical report. (src/infra/path-env.ts:83, c730d8f1f1bb)
  • PR implementation source: The PR head adds tryProcessCwd() and keeps missing-cwd absence explicit so each trust boundary chooses skip, fail, or fallback behavior. (src/infra/safe-cwd.ts:3, 395b1e5cf2b2)
  • Owner-boundary implementation: The PR skips project-local bins when cwd is unavailable, fails required-home resolution with actionable guidance when home and cwd are both unavailable, and refuses TUI local shell commands instead of retargeting them. (src/tui/tui-local-shell.ts:102, 395b1e5cf2b2)
  • Regression tests: The PR adds focused tests for deleted-cwd dotenv fallback, required-home failure, PATH project-local skip, TUI agent fallback, and local-shell refusal. (src/infra/dotenv.test.ts:218, 395b1e5cf2b2)
  • Related canonical issue: The PR uses closing syntax for [Bug]: CLI crashes when current working directory is deleted (uv_cwd error not handled) #73676, whose report gives reproducible macOS/npm-global deleted-cwd steps for openclaw tui and an ENOENT: uv_cwd crash.

Likely related people:

  • steipete: Authored the current PR head rewrite and has the dominant shortlog history across the touched home-dir, CLI, PATH, and TUI files. (role: current rewrite author and adjacent owner; confidence: high; commits: 395b1e5cf2b2, 7119ab1d98d7, 013e8f6b3be3; files: src/infra/home-dir.ts, src/infra/path-env.ts, src/tui/tui.ts)
  • vincentkoc: Assigned/reviewed this PR, identified the caller-specific fallback requirements, and has recent merged history around dotenv, CLI, and shell execution boundaries. (role: reviewer and adjacent CLI/dotenv owner; confidence: high; commits: b7615e0ce37f, 330a9f98cb29, 11590eb6ce38; files: src/tui/tui-local-shell.ts, src/infra/dotenv.ts, src/cli/run-main.ts)
  • vignesh07: Recent shortlog/history shows repeated TUI ownership, including local shell buffering and terminal behavior near the affected TUI local-shell surface. (role: TUI adjacent contributor; confidence: medium; commits: 542271e30515, b4cdffc7a429, fca0467082cb; files: src/tui/tui.ts, src/tui/tui-local-shell.ts)
  • flashosophy: Current-main blame for many touched lines points to the merged TUI stream rewrite, though that appears to be a broad recent touch rather than deleted-cwd-specific ownership. (role: recent current-main line author; confidence: low; commits: 3f1dea78753b; files: src/tui/tui.ts, src/tui/tui-local-shell.ts, src/infra/home-dir.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (6 earlier review cycles)
  • reviewed 2026-06-26T17:03:28.685Z sha 0e24b55 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T17:25:20.160Z sha 83376b1 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T17:35:54.803Z sha 83376b1 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T18:07:17.754Z sha 7a6b0ac :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T18:18:46.885Z sha 5d35e77 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T18:34:39.732Z sha ede4604 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 22, 2026
ml12580 added a commit to ml12580/openclaw that referenced this pull request Jun 22, 2026
Rework per maintainer review on openclaw#93636: drop the generic safeCwd()->HOME
fallback in favor of nullable cwd handling (tryProcessCwd), with each
caller choosing its own behavior:
- dotenv: skip workspace .env (already done)
- PATH: skip project-local bin lookup when cwd is null (was wrongly
  remapping to $HOME/node_modules/.bin, changing PATH trust semantics)
- required-home: fall back to the running Node binary dir (not os.tmpdir
  shared-temp, not a generic HOME that is already empty in this branch)
- TUI: cover runTui, resolveLocalAuthSpawnCwd, and
  resolveInitialTuiAgentId (previously unguarded bare process.cwd())
- tui-local-shell: fall back to os.homedir() for !cmd spawn cwd

Adopts the nullable-cwd design from PR openclaw#93034 (the endorsed repair base),
diverging on the required-home fallback (execPath dir instead of tmpdir).
Closes openclaw#73676.
@steipete
steipete requested a review from a team as a code owner July 5, 2026 18:11
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord channel: imessage Channel integration: imessage channel: telegram Channel integration: telegram channel: voice-call Channel integration: voice-call channel: zalo Channel integration: zalo extensions: memory-core Extension: memory-core commands Command implementations agents Agent runtime and tooling extensions: openai extensions: qa-lab extensions: codex extensions: google labels Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot removed docs Improvements or additions to documentation channel: discord Channel integration: discord channel: imessage Channel integration: imessage channel: telegram Channel integration: telegram channel: voice-call Channel integration: voice-call channel: zalo Channel integration: zalo app: android App: android app: web-ui App: web-ui gateway Gateway runtime extensions: memory-core Extension: memory-core scripts Repository scripts labels Jul 5, 2026
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Land-ready on clean exact head 395b1e5cf2b2da6b34145173aa098dc8eb73c0bf.

  • Rewritten to one 14-file commit on current main; unrelated accumulated rebase history removed; @ml12580 credit preserved with Co-authored-by.
  • Blacksmith Testbox tbx_01kwsmjrh13za4ghjn0kcrhfjt / run 28748684029: 147 focused tests passed.
  • Blacksmith Testbox tbx_01kwskqhr1tm4d5r3g5vwh7ce8 / run 28748286393: exact check:changed passed; real deleted-CWD CLI/TUI tmux proof and 24 PTY fake/local/Gateway cases passed.
  • Fresh autoreview: no accepted/actionable findings (confidence 0.94).
  • Hosted CI/Testbox for this exact clean head is green; no known proof gaps.

Co-authored-by: ml12580 <long.xinyuan3@xydigit.com>
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes P2 Normal backlog priority with limited blast radius. size: S triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: CLI crashes when current working directory is deleted (uv_cwd error not handled)

3 participants