--- a/crates/turborepo-lib/src/engine/builder.rs
+++ b/crates/turborepo-lib/src/engine/builder.rs
@@ -732,16 +732,18 @@ impl<'a> EngineBuilder<'a> {
                 .load(package_name)
                 .map(Some)
                 .or_else(|err| {
-                    if let Some((span, text)) = read_req.required()
-                        && matches!(err, config::Error::NoTurboJSON)
-                    {
-                        Err(Error::MissingTurboJsonExtends(Box::new(
-                            MissingTurboJsonExtends {
-                                package_name: read_req.package_name().to_string(),
-                                span,
-                                text,
-                            },
-                        )))
+                    if let Some((span, text)) = read_req.required() {
+                        if matches!(err, config::Error::NoTurboJSON) {
+                            Err(Error::MissingTurboJsonExtends(Box::new(
+                                MissingTurboJsonExtends {
+                                    package_name: read_req.package_name().to_string(),
+                                    span,
+                                    text,
+                                },
+                            )))
+                        } else {
+                            Err(err.into())
+                        }
                     } else if matches!(err, config::Error::NoTurboJSON) {
                         Ok(None)
                     } else {
--- a/crates/turborepo-lib/src/lib.rs
+++ b/crates/turborepo-lib/src/lib.rs
@@ -4,7 +4,6 @@
 #![feature(once_cell_try)]
 #![feature(try_blocks)]
 #![feature(impl_trait_in_assoc_type)]
-#![feature(let_chains)]
 #![deny(clippy::all)]
 // Clippy's needless mut lint is buggy: https://github.com/rust-lang/rust-clippy/issues/11299
 #![allow(clippy::needless_pass_by_ref_mut)]
--- a/crates/turborepo-lib/src/turbo_json/validator.rs
+++ b/crates/turborepo-lib/src/turbo_json/validator.rs
@@ -98,28 +98,27 @@ pub fn validate_extends(validator: &Validator, turbo_json: &TurboJson) -> Vec<Er
             text: NamedSource::new(path, text),
         }];
     }
-    if let Some(package_name) = turbo_json.extends.first()
-        && package_name != ROOT_PKG_NAME
-        && validator.non_root_extends
-    {
-        let path = turbo_json
-            .path
-            .as_ref()
-            .map_or("turbo.json", |p| p.as_ref());
+    if let Some(package_name) = turbo_json.extends.first() {
+        if package_name != ROOT_PKG_NAME && validator.non_root_extends {
+            let path = turbo_json
+                .path
+                .as_ref()
+                .map_or("turbo.json", |p| p.as_ref());
 
-        let (span, text) = match turbo_json.text {
-            Some(ref text) => {
-                let len = text.len();
-                let span: SourceSpan = (0, len - 1).into();
-                (Some(span), text.to_string())
-            }
-            None => (None, String::new()),
-        };
-        // Root needs to be first
-        return vec![Error::ExtendsRootFirst {
-            span,
-            text: NamedSource::new(path, text),
-        }];
+            let (span, text) = match turbo_json.text {
+                Some(ref text) => {
+                    let len = text.len();
+                    let span: SourceSpan = (0, len - 1).into();
+                    (Some(span), text.to_string())
+                }
+                None => (None, String::new()),
+            };
+            // Root needs to be first
+            return vec![Error::ExtendsRootFirst {
+                span,
+                text: NamedSource::new(path, text),
+            }];
+        }
     }
     // If we allow for non-root extends we don't need to perform this check
     (!validator.non_root_extends
