{"record":{"id":"c98e067e03ffbb17","repo":"jdx/mise","slug":"created-path-component-was-replaced-before-it-c","errorCode":null,"errorMessage":"created path component {} was replaced before it could be opened","messagePattern":"created path component (.+?) was replaced before it could be opened","errorType":"error_code","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":1735,"sourceCode":"                        return Err(error).wrap_err_with(|| {\n                            format!(\n                                \"failed to create path component {}\",\n                                component_path.display()\n                            )\n                        });\n                    }\n                };\n                let created = openat(&directory, name.as_os_str(), flags, Mode::empty())\n                    .wrap_err_with(|| {\n                        format!(\n                            \"failed to open newly available path component {} without following symlinks\",\n                            component_path.display()\n                        )\n                    })?;\n                let stat = nix::sys::stat::fstat(&created)?;\n                if stat.st_uid != nix::unistd::geteuid().as_raw() {\n                    if created_by_us {\n                        bail!(\n                            \"created path component {} was replaced before it could be opened\",\n                            component_path.display()\n                        );\n                    } else {\n                        bail!(\n                            \"path component {} was concurrently created by another user\",\n                            component_path.display()\n                        );\n                    }\n                }\n                created\n            }\n        };\n        current.push(name);\n    }\n    Ok(directory)\n}\n","sourceCodeStart":1717,"sourceCodeEnd":1753,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/managed_files.rs#L1717-L1753","documentation":"Mise creates a missing path component with O_CREAT|O_EXCL-style semantics and then fstat()s it. If the freshly created component's owner is not the current effective UID, the path was swapped out between creation and open — a classic TOCTOU attack — so mise refuses to open the replaced component it just created.","triggerScenarios":"Another process (or attacker) replaces a component mise just created in a managed path before mise opens it; created_by_us is true and the fstat uid check fails.","commonSituations":"Two users sharing a directory where one races the other's mise operation; a tmpwatch/cleanup daemon deleting and recreating directories mid-run; malicious symlink-swapping in a writable parent.","solutions":["Re-run the mise command — transient races usually succeed on retry","Ensure no concurrent user/process is manipulating the same path","Make the parent directory owned by you and not writable by others (chmod go-w)"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"import os\ndef component_owned_by_me(path):\n    return os.stat(path).st_uid == os.geteuid()","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"was replaced before it could be opened\") => {\n        // transient race: back off briefly and retry once\n    }\n    r => r,\n}","preventionTips":["Run only one mise instance per data directory at a time","Avoid sharing mise paths between multiple Unix users","Disable aggressive cleanup daemons on mise data directories","Keep parent dirs writable only by the current user"],"tags":["filesystem","race-condition","security","toctou"],"backgroundTag":"file-already-exists","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}