diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs
index fd2e4bb5e13..41c4bfdb269 100644
--- a/src/cargo/sources/path.rs
+++ b/src/cargo/sources/path.rs
@@ -11,9 +11,7 @@ use log::{trace, warn};
 use crate::core::source::MaybePackage;
 use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary};
 use crate::ops;
-use crate::util::paths;
-use crate::util::Config;
-use crate::util::{internal, CargoResult};
+use crate::util::{internal, paths, CargoResult, CargoResultExt, Config};
 
 pub struct PathSource<'cfg> {
     source_id: SourceId,
@@ -455,7 +453,10 @@ impl<'cfg> PathSource<'cfg> {
         //
         // TODO: drop `collect` and sort after transition period and dropping warning tests.
         // See rust-lang/cargo#4268 and rust-lang/cargo#4270.
-        let mut entries: Vec<PathBuf> = fs::read_dir(path)?.map(|e| e.unwrap().path()).collect();
+        let mut entries: Vec<PathBuf> = fs::read_dir(path)
+            .chain_err(|| format!("cannot read {:?}", path))?
+            .map(|e| e.unwrap().path())
+            .collect();
         entries.sort_unstable_by(|a, b| a.as_os_str().cmp(b.as_os_str()));
         for path in entries {
             let name = path.file_name().and_then(|s| s.to_str());
diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs
index 106f1b1c8fa..3303327fea9 100644
--- a/tests/testsuite/build_script.rs
+++ b/tests/testsuite/build_script.rs
@@ -3720,9 +3720,7 @@ fn using_rerun_if_changed_does_not_rebuild() {
         .build();
 
     p.cargo("build").run();
-    p.cargo("build")
-        .with_stderr("[FINISHED] [..]")
-        .run();
+    p.cargo("build").with_stderr("[FINISHED] [..]").run();
 }
 
 #[test]
@@ -3807,3 +3805,32 @@ fn links_interrupted_can_restart() {
         .with_stderr_contains("[RUNNING] [..]/foo-[..]/build-script-build[..]")
         .run();
 }
+
+#[test]
+#[cfg(unix)]
+fn build_script_scan_eacces() {
+    // build.rs causes a scan of the whole project, which can be a problem if
+    // a directory is not accessible.
+    use std::os::unix::fs::PermissionsExt;
+    let p = project()
+        .file("src/lib.rs", "")
+        .file("build.rs", "fn main() {}")
+        .file("secrets/stuff", "")
+        .build();
+    let path = p.root().join("secrets");
+    fs::set_permissions(&path, fs::Permissions::from_mode(0)).unwrap();
+    // "Caused by" is a string from libc such as the following:
+    //   Permission denied (os error 13)
+    p.cargo("build")
+        .with_stderr(
+            "\
+[ERROR] cannot read \"[..]/foo/secrets\"
+
+Caused by:
+  [..]
+",
+        )
+        .with_status(101)
+        .run();
+    fs::set_permissions(&path, fs::Permissions::from_mode(0o755)).unwrap();
+}