EpicGames/lore · error · tokio::io::Error (Unsupported)
Unable to rename, file/directory mismatch
Error message
Unable to rename, file/directory mismatch
What it means
`unify_name_case_rename` fixes a path's on-disk casing by renaming it. Before renaming it compares the dir/file kind of the source and destination metadata; if one is a directory and the other is not (or vice versa), it refuses with `ErrorKind::Unsupported`, because renaming between kinds would silently move different objects. This is a safety check against merging a file and a directory that share the same case-folded name.
Solutions
- Inspect both paths' metadata; resolve the file/dir collision manually (delete or move one of the entries).
- Recompute the rename plan after the collision is resolved.
- Catch `ErrorKind::Unsupported` and skip/queue the entry for manual resolution instead of retrying.
Example fix
// before
unify_name_case_rename(from, to).await?;
// after
let (f, t) = (metadata(from).await?, metadata(to).await?);
if f.is_dir() != t.is_dir() {
eprintln!("kind mismatch between {from:?} and {to:?}; resolve manually");
} else {
unify_name_case_rename(from, to).await?;
} Defensive patterns
Strategy: validation
Validate before calling
let from_meta = tokio::fs::metadata(&from_path).await?;
let to_meta = tokio::fs::metadata(&to_path).await?;
if from_meta.is_dir() != to_meta.is_dir() {
// resolve the file/dir collision before renaming
} Try / catch
match unify_name_case_rename(&from, &to).await {
Err(e) if e.kind() == io::ErrorKind::Unsupported => {
eprintln!("kind mismatch {from:?} <-> {to:?}; needs manual fix");
}
other => other?,
} Prevention
- Compare source/target metadata (is_dir) before any case-unifying rename.
- On case-insensitive filesystems, expect folded-name collisions between files and dirs.
- Regenerate rename plans after any change to entry types.
When it happens
Trigger: Calling `unify_name_case_rename` where the source path and target path resolve to entries of different kinds — e.g. source is a file but the target name collides with an existing directory (or the driver's metadata for either path points at a different object than expected on a case-insensitive filesystem).
Common situations: Case-insensitive filesystems (macOS/Windows default) where 'Foo.txt' and 'foo.txt' are the same entry, but one path is a dir and the other a file; stale plans generated before the entry's type changed.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- failed to create directory
- failed to write ephemeral certificate
- failed to write ephemeral private key
- file refused further writes
- file ended before the requested read length
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/2949f7a700ddfed4.
Report an issue: GitHub.
Appendix: source
Thrown at lore-revision/src/util/fs.rs:830
to_path: &'a Path,
) -> Pin<Box<dyn Future<Output = std::io::Result<()>> + Send + 'a>> {
Box::pin(async move {
let driver = lore_io::IoDriver::global();
lore_debug!(
"Try rename {} -> {}",
from_path.display(),
to_path.display()
);
if driver.rename(from_path, to_path).await.is_ok() {
lore_debug!("Renamed {} -> {}", from_path.display(), to_path.display());
return Ok(());
}
let from_metadata = driver.metadata(from_path).await?;
let to_metadata = driver.metadata(to_path).await?;
if from_metadata.is_dir() != to_metadata.is_dir() {
return Err(tokio::io::Error::new(
std::io::ErrorKind::Unsupported,
"Unable to rename, file/directory mismatch",
));
}
if from_metadata.is_file() {
lore_debug!(
"Failed rename {} -> {}, replacing",
from_path.display(),
to_path.display()
);
driver.remove_file(to_path).await?;
if let Err(err) = driver.rename(from_path, to_path).await {
lore_debug!(
"Failed rename {} -> {}, try copy and delete: {err}",
from_path.display(),
to_path.display(),
);View on GitHub (pinned to 074eb0b0d1)