diff --git a/crates/nu-command/src/core_commands/let_.rs b/crates/nu-command/src/core_commands/let_.rs index 090893854f..4d419dc146 100644 --- a/crates/nu-command/src/core_commands/let_.rs +++ b/crates/nu-command/src/core_commands/let_.rs @@ -60,19 +60,22 @@ impl Command for Let { .as_keyword() .expect("internal error: missing keyword"); - let rhs = eval_expression_with_input( + let (rhs, external_failed) = eval_expression_with_input( engine_state, stack, keyword_expr, input, call.redirect_stdout, call.redirect_stderr, - )? - .0; - - stack.add_var(var_id, rhs.into_value(call.head)); - - Ok(PipelineData::empty()) + )?; + if external_failed { + // rhs must be a PipelineData::ExternalStream and it's failed + // return the failed stream (with a non-zero exit code) so the engine knows to stop running + Ok(rhs) + } else { + stack.add_var(var_id, rhs.into_value(call.head)); + Ok(PipelineData::empty()) + } } fn examples(&self) -> Vec { diff --git a/crates/nu-command/tests/commands/let_.rs b/crates/nu-command/tests/commands/let_.rs index d2db3e5877..ec207a666a 100644 --- a/crates/nu-command/tests/commands/let_.rs +++ b/crates/nu-command/tests/commands/let_.rs @@ -25,3 +25,13 @@ fn let_doesnt_mutate() { assert!(actual.err.contains("immutable")); } + +#[test] +fn let_with_external_failed() { + let actual = nu!( + cwd: ".", + pipeline(r#"let x = nu --testbin outcome_err "aa"; echo fail"#) + ); + + assert!(!actual.out.contains("fail")); +}