{"record":{"id":"acb29593f7b95c4e","repo":"can1357/oh-my-pi","slug":"0-acb295","errorCode":null,"errorMessage":"{0}","messagePattern":"\\{0\\}","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/pi-builtins/src/mv.rs","lineNumber":79,"sourceCode":"\t#[error(\"cannot overwrite directory {0} with non-directory\")]\n\tDirectoryToNonDirectory(String),\n\t#[error(\"cannot overwrite non-directory {1} with directory {0}\")]\n\tNonDirectoryToDirectory(String, String),\n\t#[error(\"target {0}: Not a directory\")]\n\tNotADirectory(String),\n\t#[error(\"target directory {0}: Not a directory\")]\n\tTargetNotADirectory(String),\n\t#[error(\"failed to access {0}: Not a directory\")]\n\tFailedToAccessNotADirectory(String),\n}\n\n#[derive(Debug, Error)]\nenum MvFailure {\n\t#[error(transparent)]\n\tMove(#[from] MvError),\n\t#[error(transparent)]\n\tIo(#[from] io::Error),\n\t#[error(\"{0}\")]\n\tMessage(String),\n}\n\ntype MvResult<T> = Result<T, MvFailure>;\n\n/// Parsed `mv` invocation.\npub(crate) struct Mv {\n\tmatches: ArgMatches,\n}\n\nmatches_parser!(Mv, app);\n\n/// A terminal-like indicatif sink backed by the command's stderr.\nstruct ProgressTerminal {\n\twriter: Mutex<OpenFile>,\n}\n\nimpl fmt::Debug for ProgressTerminal {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/mv.rs#L61-L97","documentation":"MvFailure::Message(String) is the catch-all variant of mv's failure enum. It wraps a free-form diagnostic string verbatim ({0} is the string itself) with no additional context, unlike MvError or io::Error variants which add their own prefixes. When you see a bare message with no `mv:`-style formatting, it came from code that formatted its own complete error text and wrapped it via MvFailure::Message (or an equivalent .into()).","triggerScenarios":"Any code path in mv that constructs a custom error string and converts it to MvFailure::Message instead of a structured MvError or io::Error; since the variant is transparent ({0}), the output is exactly that string with no source path or error-kind decoration.","commonSituations":"Debugging mv failures whose messages lack the usual `cannot stat`/`target` prefixes, making them hard to grep for; downstream tooling that pattern-matches mv's stderr will not recognize these bare messages; contributor code that used format!(...).into() for an error.","solutions":["Read the message text itself - it is the complete diagnostic; there is no hidden cause or error kind","Match the failure in code with `MvFailure::Message(ref s)` and inspect the string, since it carries no io::ErrorKind","If you maintain this code, prefer a structured MvError or io::Error::new(kind, msg) variant so callers can match on error kinds instead of strings"],"exampleFix":"// before\nreturn Err(format!(\"custom failure for {path}\").into()); // -> MvFailure::Message\n// after\nreturn Err(io::Error::new(io::ErrorKind::InvalidInput, format!(\"custom failure for {path}\")).into());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_message_failure(f: &MvFailure) -> Option<&str> {\n  match f { MvFailure::Message(s) => Some(s.as_str()), _ => None }\n}","tryCatchPattern":"match mv_result {\n  Err(MvFailure::Message(msg)) => {\n    log::warn!(\"mv failed with unstructured message: {msg}\");\n    // handle by string content; no ErrorKind available\n  }\n  Err(other) => return Err(other),\n  Ok(_) => {}\n}","preventionTips":["Do not pattern-match these errors by exact text; the variant is free-form","When embedding mv, prefer capturing stderr and matching io::ErrorKind-carrying variants (Move/Io) instead of Message","If you control the code, replace ad-hoc Message(...) errors with typed variants for machine handling"],"tags":["mv","error-handling","rust","diagnostics"],"backgroundTag":"unstructured-error-message","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}