Skip to content

feat(cli): handle non-existent working directories gracefully#6304

Merged
jdx merged 2 commits intomainfrom
feat/handle-nonexistent-cwd
Sep 15, 2025
Merged

feat(cli): handle non-existent working directories gracefully#6304
jdx merged 2 commits intomainfrom
feat/handle-nonexistent-cwd

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Sep 15, 2025

Summary

  • Shows a warning when mise is run from a non-existent directory
  • Allows commands to continue execution despite the missing directory
  • Prevents panics and provides helpful context to users

Background

Previously, mise would panic when run from a directory that no longer exists (e.g., after the directory was deleted while the shell was still in it). This could happen when:

  • A directory is deleted while a shell session is still active in it
  • Running mise from a symlink that no longer resolves
  • File system issues cause the current directory to become inaccessible

Changes

  1. Added warning in cli/mod.rs: Shows warning after logger initialization
  2. Warning message: Shows the problematic directory path (from PWD env var if available)
  3. All commands continue: No need to maintain an allowlist of commands
  4. Fixed config_root.rs panic: Handle absolutize() failures gracefully
  5. Comprehensive e2e test: Added test coverage for various scenarios

Approach

Instead of blocking certain commands or maintaining an allowlist, mise now:

  • Shows a warning to inform the user their directory doesn't exist
  • Continues execution, allowing commands to work as much as possible
  • This is more robust and user-friendly than selective blocking

Test Plan

  • Added e2e test test_nonexistent_cwd that tests multiple mise commands
  • Manually tested warning appears for all commands
  • Verified commands still work despite the warning
  • All existing tests pass

Example Warning

mise WARN  Current directory does not exist or is not accessible: /tmp/deleted_dir

Platform Support

  • The code is cross-platform (Linux, macOS, Windows)
  • The e2e test is bash-based (Unix only), but the functionality works on Windows

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings September 15, 2025 16:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds graceful error handling when mise is run from a non-existent working directory, preventing panics and providing friendly error messages. Previously, mise would panic if the current directory was deleted while a shell session was active in it.

  • Added early directory existence check in main.rs with selective command allowlist
  • Fixed config_root.rs to handle absolutize() failures gracefully
  • Added comprehensive e2e test coverage for various scenarios

Reviewed Changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/main.rs Added current directory validation with allowlist for commands that don't require cwd
src/config/config_file/config_root.rs Changed unwrap_or to unwrap_or_else to handle absolutize failures
e2e/cli/test_nonexistent_cwd Added comprehensive test script for non-existent directory scenarios

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

src/main.rs Outdated
Comment on lines +129 to +136
let cwd_not_required = args.iter().any(|arg| {
arg == "--version" || arg == "-V" ||
arg == "--help" || arg == "-h" ||
arg == "ls" || arg == "list" || // ls can show global tools
arg == "doctor" || arg == "dr" || // doctor can run without cwd
arg == "plugins" || arg == "p" || // plugins list doesn't need cwd
arg == "version" || arg == "v" // version info doesn't need cwd
});
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded command list creates maintenance burden. Consider extracting this into a constant array or method to improve maintainability and make it easier to add new commands that don't require cwd.

Copilot uses AI. Check for mistakes.
src/main.rs Outdated
arg == "ls" || arg == "list" || // ls can show global tools
arg == "doctor" || arg == "dr" || // doctor can run without cwd
arg == "plugins" || arg == "p" || // plugins list doesn't need cwd
arg == "version" || arg == "v" // version info doesn't need cwd
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line duplicates the version check from line 130. The --version/-V flags and version/v subcommands should be consolidated to avoid redundancy.

Copilot uses AI. Check for mistakes.
cursor[bot]

This comment was marked as outdated.

Previously, mise would panic when run from a directory that no longer exists
(e.g., after the directory was deleted while the shell was still in it).
This change adds proper error handling to provide a friendly error message
instead of panicking.

Changes:
- Add early check for current directory existence in main.rs
- Provide clear error message showing the problematic directory path
- Allow certain commands (--version, ls, doctor, etc.) to work without cwd
- Fix panic in config_root.rs when absolutize() fails
- Add comprehensive e2e test for non-existent directory scenarios

Fixes the panic that occurred when running mise commands from deleted directories.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@jdx jdx force-pushed the feat/handle-nonexistent-cwd branch from a04c54a to 51369b9 Compare September 15, 2025 16:24
Move the working directory check logic into a dedicated helper function
check_working_directory() for better code organization and maintainability.
@jdx jdx enabled auto-merge (squash) September 15, 2025 16:31
@github-actions
Copy link

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.10 x -- echo 19.4 ± 0.5 18.7 24.6 1.00
mise x -- echo 19.6 ± 0.6 18.8 21.8 1.01 ± 0.04

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.10 env 19.0 ± 0.9 18.3 32.9 1.00
mise env 19.1 ± 0.6 18.3 22.9 1.01 ± 0.06

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.10 hook-env 18.7 ± 0.6 17.9 20.3 1.01 ± 0.04
mise hook-env 18.5 ± 0.5 17.9 21.0 1.00

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.10 ls 16.9 ± 0.7 15.8 18.8 1.03 ± 0.05
mise ls 16.4 ± 0.5 15.8 18.9 1.00

xtasks/test/perf

Command mise-2025.9.10 mise Variance
install (cached) 168ms ✅ 104ms +61%
ls (cached) 63ms 63ms +0%
bin-paths (cached) 70ms 70ms +0%
task-ls (cached) 487ms 482ms +1%

✅ Performance improvement: install cached is 61%

@jdx jdx merged commit 1bf0bc3 into main Sep 15, 2025
18 checks passed
@jdx jdx deleted the feat/handle-nonexistent-cwd branch September 15, 2025 16:43
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Sep 19, 2025
## [2025.9.12](https://github.com/jdx/mise/compare/v2025.9.11..v2025.9.12) - 2025-09-16

### 🐛 Bug Fixes

- **(ci)** properly exclude aqua-registry files from hk linting by @jdx in [42d7758](jdx/mise@42d7758)

### Chore

- **(release)** embed aqua-registry under crate and publish like vfox by @jdx in [#6306](jdx/mise#6306)
- ignore aqua-registry assets from prettier by @jdx in [047d77b](jdx/mise@047d77b)
- disable "useless cat" shellcheck by @jdx in [a6def59](jdx/mise@a6def59)

## [2025.9.11](https://github.com/jdx/mise/compare/v2025.9.10..v2025.9.11) - 2025-09-16

### 📦 Registry

- indicate aws-cli is v2 by @jayvdb in [#6300](jdx/mise#6300)

### 🚀 Features

- **(ci)** run all registry tools when workflow_dispatch is triggered by @jdx in [#6295](jdx/mise#6295)
- **(cli)** handle non-existent working directories gracefully by @jdx in [#6304](jdx/mise#6304)
- **(set)** add -E/--env flag to mise set command by @jdx in [#6291](jdx/mise#6291)
- **(tasks)** make auto outputs default by @risu729 in [#6137](jdx/mise#6137)

### 🐛 Bug Fixes

- align crate versions to fix release-plz script by @jdx in [5a464e9](jdx/mise@5a464e9)

### 🚜 Refactor

- **(aqua)** extract aqua registry into internal subcrate by @jdx in [#6293](jdx/mise#6293)

### 📚 Documentation

- fix mkdir paths by @risu729 in [#6298](jdx/mise#6298)
- fix rust profile default by @risu729 in [#6305](jdx/mise#6305)

### Chore

- **(aqua-registry)** remove unused aqua-registry files by @jdx in [#6294](jdx/mise#6294)
- **(release)** make release-plz idempotent for existing crate versions by @jdx in [dbdfd6a](jdx/mise@dbdfd6a)
- **(release)** skip publishing mise when aqua-registry is a path dep by @jdx in [47efffd](jdx/mise@47efffd)
- keep aqua-registry LICENSE file by @risu729 in [#6297](jdx/mise#6297)

### New Contributors

- @jayvdb made their first contribution in [#6300](jdx/mise#6300)

## [2025.9.10](https://github.com/jdx/mise/compare/v2025.9.9..v2025.9.10) - 2025-09-13

### 📦 Registry

- use asdf to install semver-tool by @jylenhof in [#6233](jdx/mise#6233)

### 🐛 Bug Fixes

- **(tool-stub)** detect binary names from single-file downloads by @jdx in [#6281](jdx/mise#6281)

### 🚜 Refactor

- allow any collection types in deserialize_arr by @risu729 in [#6282](jdx/mise#6282)
- use deserialize_arr for task runs by @risu729 in [#6253](jdx/mise#6253)

### 📚 Documentation

- **(getting-started)** add backends step with diagram, github example, env vars and simple tasks by @jdx in [#6288](jdx/mise#6288)
- simplify OS detection in tool plugin development by @jdx in [#6287](jdx/mise#6287)
- update backend plugin template references by @jdx in [942f5eb](jdx/mise@942f5eb)

### 📦️ Dependency Updates

- update rust crate chrono to v0.4.42 by @renovate[bot] in [#6274](jdx/mise#6274)
- update taiki-e/install-action digest to 0154864 by @renovate[bot] in [#6273](jdx/mise#6273)

### Chore

- **(schema)** fix schema for subtasks by @risu729 in [#6289](jdx/mise#6289)
- update render:schema task by @risu729 in [#6275](jdx/mise#6275)

## [2025.9.9](https://github.com/jdx/mise/compare/v2025.9.8..v2025.9.9) - 2025-09-11

### 🐛 Bug Fixes

- **(backend)** make HTTP installs atomic and serialize with cache lock by @jdx in [#6259](jdx/mise#6259)
- **(env)** allow nested env._.path directives by @risu729 in [#6160](jdx/mise#6160)
- **(env)** disallow nested env objects by @risu729 in [#6268](jdx/mise#6268)
- **(schema)** allow nested arrays in task.depends by @risu729 in [#6265](jdx/mise#6265)
- **(task)** resolve jobs=1 hang and keep-order panic; improve Ctrl-C handling by @jdx in [#6264](jdx/mise#6264)
- **(tasks)** stop CLI group after first failure without --continue-on-error by @jdx in [#6270](jdx/mise#6270)

### 📚 Documentation

- fixed toml issues in URL replacements settings documentation by @ThomasSteinbach in [#6269](jdx/mise#6269)

### Chore

- **(schema)** strict oneOf branches and DRY env_directive in schemas by @jdx in [#6271](jdx/mise#6271)
- add schema linter by @risu729 in [#6267](jdx/mise#6267)

## [2025.9.8](https://github.com/jdx/mise/compare/v2025.9.7..v2025.9.8) - 2025-09-10

### 🐛 Bug Fixes

- **(tasks)** prevent hang when task fails in sequence by @jdx in [#6260](jdx/mise#6260)
- **(version)** fetch mise version if cached version is older than the current by @risu729 in [#6252](jdx/mise#6252)

### 📦️ Dependency Updates

- update rhysd/action-setup-vim action to v1.4.3 by @renovate[bot] in [#6249](jdx/mise#6249)

## [2025.9.7](https://github.com/jdx/mise/compare/v2025.9.6..v2025.9.7) - 2025-09-09

### 🐛 Bug Fixes

- **(env)** allow mixed map for env._.file by @risu729 in [#6148](jdx/mise#6148)
- **(tasks)** restore parallel starts with poetry via list_paths cache and stable exec-env cache by @jdx in [#6237](jdx/mise#6237)
- add 'unknown' to the list of OS patterns by @efussi in [#6235](jdx/mise#6235)
- propagate errors from backend installs by @jdx in [#6236](jdx/mise#6236)

### 📦️ Dependency Updates

- update taiki-e/install-action digest to 0c5db7f by @renovate[bot] in [#6244](jdx/mise#6244)
- update golang docker tag to v1.25.1 by @renovate[bot] in [#6247](jdx/mise#6247)
- update dependency vitepress to v1.6.4 by @renovate[bot] in [#6246](jdx/mise#6246)

### New Contributors

- @efussi made their first contribution in [#6235](jdx/mise#6235)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants