Repository navigation
Closed
Labels
good first issueGood for newcomersGood for newcomersstatus:needs-triageAn issue that hasn't had any proper lookAn issue that hasn't had any proper look
Milestone
Description
Bug report form
- I have done a basic search of the issue tracker to find any existing issues that are similar.
- I have checked that my version is at least the latest stable release available via my installation method.
Describe the bug
mkdir for an existing path, including a path created by mkdir itself, returns exit code 0 as if a directory was created.
worse, mkdir --verbose reports the path as created: true.
to be clear, this doesn't match the behavior of GNU/coreutils mkdir or uutils/coreutils mkdir
How to reproduce
> cd (mktemp --directory)
> mkdir foo
> $ans.exit_code
0
> mkdir foo
> $ans.exit_code
0
> mkdir --verbose foo
╭───┬─────────────────────────────────────────────────────────────────────┬─────────┬───────╮
│ # │ path │ created │ error │
├───┼─────────────────────────────────────────────────────────────────────┼─────────┼───────┤
│ 0 │ /var/folders/n1/2s4wgvw17z75hspycqvqh8k00000gn/T/tmp.F2LC1Klmii/foo │ true │ │
╰───┴─────────────────────────────────────────────────────────────────────┴─────────┴───────╯
> ^/opt/homebrew/opt/uutils-coreutils/libexec/uubin/mkdir foo
mkdir: foo: File existsExpected behavior
error on the existing path. exit code should be 1 if at least one path was not created because it already exists (even though other paths may have been created). this matches uutils
also, mkdir --verbose should show it as an error.
Configuration
| key | value |
|---|---|
| version | 0.115.2 |
| major | 0 |
| minor | 115 |
| patch | 2 |
| branch | |
| commit_hash | f8ae9ac |
| build_os | macos-aarch64 |
| build_target | aarch64-apple-darwin |
| rust_version | rustc 1.96.1 (31fca3adb 2026-06-26) |
| rust_channel | 1.96.1-aarch64-apple-darwin |
| cargo_version | cargo 1.96.1 (356927216 2026-06-26) |
| build_time | 2026-09-06 00:17:18 +03:00 |
| build_rust_channel | release |
| allocator | standard |
| features | default, lsp, mcp, network, plugin, rustls-tls, sqlite, trash-support |
| installed_plugins | desktop_notifications 0.107.0, formats 0.107.0, highlight 1.4.9+0.107.0, json_path 0.17.1, query 0.107.0, regex 0.19.0, skim 0.22.0, strutils 0.21.0 |
| experimental_options | example=false, dc-glob=true, reorder-cell-paths=true, pipefail=true, enforce-runtime-annotations=true, native-clip=true, cell-path-types=true, background-completions=true |
Metadata
Metadata
Assignees
Labels
good first issueGood for newcomersGood for newcomersstatus:needs-triageAn issue that hasn't had any proper lookAn issue that hasn't had any proper look
Activity
mkdir errors on already-created dir (nushell#19006)
Developer1010x commentedon Sep 13, 2026
I had a look at this. The cause is one line, but the fix is a design decision rather than a bug fix, so flagging it before writing code.
crates/nu-command/src/filesystem/umkdir.rshard-codesand passes it as
Config { recursive: IS_RECURSIVE, .. }. Inuu_mkdirthe "File exists" error is raised only when recursion is off:With
recursive: truethe existing-directory case instead falls through to anOk(())branch, which is where the silent success comes from.So
mkdirin nushell is alwaysmkdir -p, which is what the description ("with intermediary directories if required") and thecreates_intermediary_directoriestest both say. The comparison in the report is against non--pmkdir —uutils mkdir -p fooon an existingfooalso exits 0 and prints nothing, as POSIX requires-pto suppress that error. So "match uutils" points in two different directions depending on which mkdir we mean.That leaves roughly three options:
--parents/-pand make the default non-recursive. Exactly matches coreutils. Also breaks everymkdir a/b/cin every existing script and config, andcreates_intermediary_directorieswith it. A large breaking change for a command people use constantly.uu_mkdirwill not report it in recursive mode.mkdirismkdir -p.One part is a plain bug under all three, though:
mkdir --verbosereportscreated: truefor a directory that already existed. Whatever is decided about the exit code, that field is simply wrong — nothing was created. It can be fixed on its own by checking existence before the call and reportingcreated: false.Happy to implement whichever direction you prefer. If it helps to make progress in the meantime, I can put up a small PR for the
--verbosecreatedfield alone, since that one does not depend on the decision above.Developer1010x commentedon Sep 13, 2026
Put up #19017 for the
--verbosecreatedfield on its own, since that part does not depend on the decision above. The exit-code question is still open — happy to follow up with whichever of the three options you land on.fix(mkdir): don't report an existing directory as created in --verbose (
feat(mkdir): add --fail-if-exists flag to error on existing directory (…
sharmis-tp commentedon Nov 12, 2026
I'd like to take this. Will add an existence check in
mkdirbefore the call.