diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 0b9f1950ea..c812280b62 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -473,6 +473,15 @@ pub fn command_not_found( }; } + // If we find a file, it's likely that the user forgot to set permissions + if Path::new(name).is_file() { + return ShellError::ExternalCommand { + label: format!("Command `{name}` not found"), + help: format!("`{name}` refers to a file that is not executable. Did you forget to to set execute permissions?"), + span, + }; + } + // We found nothing useful. Give up and return a generic error message. ShellError::ExternalCommand { label: format!("Command `{name}` not found"), diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index ff851a3293..5b9f116626 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -127,6 +127,15 @@ fn command_not_found_error_suggests_typo_fix() { assert!(actual.err.contains("timeit")); } +#[cfg(not(windows))] +#[test] +fn command_not_found_error_recognizes_non_executable_file() { + let actual = nu!("./Cargo.toml"); + assert!(actual.err.contains( + "refers to a file that is not executable. Did you forget to to set execute permissions?" + )); +} + #[test] fn command_not_found_error_shows_not_found_1() { let actual = nu!(r#"