{"record":{"id":"12b2433d808c6e3e","repo":"sxyazi/yazi","slug":"failed-to-join-new-name-with-parent-directory","errorCode":null,"errorMessage":"Failed to join new name with parent directory","messagePattern":"Failed to join new name with parent directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-actor/src/mgr/rename.rs","lineNumber":55,"sourceCode":"\t\t\t\t.position(|c| c == '.')\n\t\t\t\t.filter(|_| hovered.is_file())\n\t\t\t\t.map(|i| name.chars().count() - i - 1)\n\t\t\t\t.filter(|&i| i != 0),\n\t\t\t_ => None,\n\t\t};\n\n\t\tlet (tab, old) = (cx.tab().id, hovered.url_owned());\n\t\tlet mut input =\n\t\t\tinput!(cx, YAZI.input.rename(hovered.is_dir()).with_value(name).with_cursor(cursor))?;\n\n\t\ttokio::spawn(async move {\n\t\t\tlet Some(InputEvent::Submit(name)) = input.recv().await else { return Ok(()) };\n\t\t\tif name.is_empty() {\n\t\t\t\treturn Ok(());\n\t\t\t}\n\n\t\t\tlet Some(Ok(new)) = old.parent().map(|u| u.try_join(name)) else {\n\t\t\t\tbail!(\"Failed to join new name with parent directory\");\n\t\t\t};\n\n\t\t\tif form.force || Self::try_ask(&old, &new).await? {\n\t\t\t\tSelf::r#do(tab, old, new).await?;\n\t\t\t}\n\t\t\tOk::<(), anyhow::Error>(())\n\t\t});\n\t\tsucc!();\n\t}\n}\n\nimpl Rename {\n\tasync fn r#do(tab: Id, old: UrlBuf, new: UrlBuf) -> Result<()> {\n\t\tlet Some((old_t, old_k)) = old.pair() else { return Ok(()) };\n\t\tlet Some(_) = new.pair() else { return Ok(()) };\n\t\tlet _permit = WATCHER.acquire().await.unwrap();\n\n\t\tlet overwritten = engine::casefold(&new).await;","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/sxyazi/yazi/blob/a541adde4e5b082719a0f21a87eb3eab071ece58/yazi-actor/src/mgr/rename.rs#L37-L73","documentation":"During interactive rename, after the user submits a new name, yazi builds the new URL by joining the submitted name onto the old file's parent via `try_join`. If the old URL has no parent (root-level entry) or the join fails (invalid name for the scheme, e.g. containing forbidden separators), the rename is aborted with this bail.","triggerScenarios":"Submitting a non-empty name in the rename input where `old.parent()` is None (file at scheme root) or `try_join(name)` returns Err because the name contains path separators, NUL bytes, or is otherwise invalid for the URL scheme.","commonSituations":"User renames a file located at `/` or at the root of a remote/scheme mount; user pastes a name containing `/` or `\\` into the rename prompt; a plugin drives rename programmatically with an entry whose URL is a scheme root.","solutions":["Submit a plain filename without path separators in the rename prompt","Move the file out of the scheme root into a real directory before renaming","In custom code, check `old.parent()` and validate `name` (no `/`, non-empty) before calling `mgr:rename`"],"exampleFix":"// before\nact!(mgr:rename, cx, (old_url, name_with_slash))?  // bails\n// after\nlet name = name_with_slash.replace('/', \"_\");\nact!(mgr:rename, cx, (old_url, name))?","handlingStrategy":"validation","validationCode":"fn valid_rename_target(old: &Url, name: &str) -> bool {\n    !name.is_empty()\n        && !name.contains('/')\n        && !name.contains('\\\\')\n        && old.parent().is_some()\n}","typeGuard":"fn renameable(old: &Url, name: &str) -> bool {\n    valid_rename_target(old, name)\n}","tryCatchPattern":"match mgr_rename(cx, old, name).await {\n    Err(e) if e.to_string().contains(\"Failed to join new name\") => {\n        notify::warn(\"Name is invalid for this location (no separators allowed)\");\n    }\n    other => other?,\n}","preventionTips":["Sanitize user-submitted names: strip '/' and '\\\\' before rename","Skip rename for entries whose URL parent() is None","Validate names at the input-prompt submit handler"],"tags":["filesystem","rename","path-validation","yazi"],"backgroundTag":"invalid-path-join","analyzedSha":"a541adde4e5b082719a0f21a87eb3eab071ece58","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}