diff --git a/src/bin/cargo/commands/login.rs b/src/bin/cargo/commands/login.rs
index 014a9384913..fb36c5ad51a 100644
--- a/src/bin/cargo/commands/login.rs
+++ b/src/bin/cargo/commands/login.rs
@@ -5,7 +5,7 @@ use std::io::{self, BufRead};
 use cargo::core::{Source, SourceId};
 use cargo::ops;
 use cargo::sources::RegistrySource;
-use cargo::util::{CargoError, CargoResultExt};
+use cargo::util::CargoResultExt;
 
 pub fn cli() -> App {
     subcommand("login")
@@ -49,7 +49,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
                 .lock()
                 .read_line(&mut line)
                 .chain_err(|| "failed to read stdin")
-                .map_err(CargoError::from)?;
+                .map_err(failure::Error::from)?;
             line.trim().to_string()
         }
     };
diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs
index 8f10c991992..df652f913d7 100644
--- a/src/cargo/core/dependency.rs
+++ b/src/cargo/core/dependency.rs
@@ -10,7 +10,7 @@ use serde::Serialize;
 
 use crate::core::interning::InternedString;
 use crate::core::{PackageId, SourceId, Summary};
-use crate::util::errors::{CargoError, CargoResult, CargoResultExt};
+use crate::util::errors::{CargoResult, CargoResultExt};
 use crate::util::{Cfg, CfgExpr, Config};
 
 /// Information about a dependency requested by a Cargo manifest.
@@ -449,7 +449,7 @@ impl ser::Serialize for Platform {
 }
 
 impl FromStr for Platform {
-    type Err = CargoError;
+    type Err = failure::Error;
 
     fn from_str(s: &str) -> CargoResult<Platform> {
         if s.starts_with("cfg(") && s.ends_with(')') {
diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs
index 8c047cf416b..9a37ff0dbd3 100644
--- a/src/cargo/core/resolver/encode.rs
+++ b/src/cargo/core/resolver/encode.rs
@@ -8,7 +8,7 @@ use serde::ser;
 use serde::{Deserialize, Serialize};
 
 use crate::core::{Dependency, Package, PackageId, SourceId, Workspace};
-use crate::util::errors::{CargoError, CargoResult, CargoResultExt};
+use crate::util::errors::{CargoResult, CargoResultExt};
 use crate::util::{internal, Graph};
 
 use super::Resolve;
@@ -276,7 +276,7 @@ impl fmt::Display for EncodablePackageId {
 }
 
 impl FromStr for EncodablePackageId {
-    type Err = CargoError;
+    type Err = failure::Error;
 
     fn from_str(s: &str) -> CargoResult<EncodablePackageId> {
         let mut s = s.splitn(3, ' ');
diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs
index 0ad672ab99d..8720f3f1009 100644
--- a/src/cargo/core/resolver/errors.rs
+++ b/src/cargo/core/resolver/errors.rs
@@ -3,7 +3,7 @@ use std::fmt;
 
 use crate::core::{Dependency, PackageId, Registry, Summary};
 use crate::util::lev_distance::lev_distance;
-use crate::util::{CargoError, Config};
+use crate::util::Config;
 use failure::{Error, Fail};
 use semver;
 
@@ -52,7 +52,7 @@ impl fmt::Display for ResolveError {
 pub type ActivateResult<T> = Result<T, ActivateError>;
 
 pub enum ActivateError {
-    Fatal(CargoError),
+    Fatal(failure::Error),
     Conflict(PackageId, ConflictReason),
 }
 
diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs
index 177371d66fe..40b7db71fac 100644
--- a/src/cargo/lib.rs
+++ b/src/cargo/lib.rs
@@ -27,7 +27,7 @@ use crate::core::shell::Verbosity::Verbose;
 use crate::core::Shell;
 
 pub use crate::util::errors::Internal;
-pub use crate::util::{CargoError, CargoResult, CliError, CliResult, Config};
+pub use crate::util::{CargoResult, CliError, CliResult, Config};
 
 pub const CARGO_ENV: &str = "CARGO";
 
@@ -126,7 +126,7 @@ pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
     std::process::exit(exit_code)
 }
 
-pub fn handle_error(err: &CargoError, shell: &mut Shell) {
+pub fn handle_error(err: &failure::Error, shell: &mut Shell) {
     debug!("handle_error; err={:?}", err);
 
     let _ignored_result = shell.error(err);
diff --git a/src/cargo/ops/cargo_read_manifest.rs b/src/cargo/ops/cargo_read_manifest.rs
index 5ea6669ab09..44115202dff 100644
--- a/src/cargo/ops/cargo_read_manifest.rs
+++ b/src/cargo/ops/cargo_read_manifest.rs
@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
 use log::{info, trace};
 
 use crate::core::{EitherManifest, Package, PackageId, SourceId};
-use crate::util::errors::{CargoError, CargoResult};
+use crate::util::errors::CargoResult;
 use crate::util::important_paths::find_project_manifest_exact;
 use crate::util::toml::read_manifest;
 use crate::util::{self, Config};
@@ -41,7 +41,7 @@ pub fn read_packages(
 ) -> CargoResult<Vec<Package>> {
     let mut all_packages = HashMap::new();
     let mut visited = HashSet::<PathBuf>::new();
-    let mut errors = Vec::<CargoError>::new();
+    let mut errors = Vec::<failure::Error>::new();
 
     trace!(
         "looking for root package: {}, source_id={}",
@@ -111,7 +111,7 @@ fn walk(path: &Path, callback: &mut dyn FnMut(&Path) -> CargoResult<bool>) -> Ca
         Err(ref e) if e.kind() == io::ErrorKind::PermissionDenied => return Ok(()),
         Err(e) => {
             let cx = format!("failed to read directory `{}`", path.display());
-            let e = CargoError::from(e);
+            let e = failure::Error::from(e);
             return Err(e.context(cx).into());
         }
     };
@@ -134,7 +134,7 @@ fn read_nested_packages(
     source_id: SourceId,
     config: &Config,
     visited: &mut HashSet<PathBuf>,
-    errors: &mut Vec<CargoError>,
+    errors: &mut Vec<failure::Error>,
 ) -> CargoResult<()> {
     if !visited.insert(path.to_path_buf()) {
         return Ok(());
diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs
index 316ca9b7092..e95dac32205 100644
--- a/src/cargo/sources/git/utils.rs
+++ b/src/cargo/sources/git/utils.rs
@@ -13,7 +13,7 @@ use serde::Serialize;
 use url::Url;
 
 use crate::core::GitReference;
-use crate::util::errors::{CargoError, CargoResult, CargoResultExt};
+use crate::util::errors::{CargoResult, CargoResultExt};
 use crate::util::paths;
 use crate::util::process_builder::process;
 use crate::util::{internal, network, Config, Progress, ToUrl};
@@ -69,7 +69,7 @@ pub struct GitDatabase {
 
 /// `GitCheckout` is a local checkout of a particular revision. Calling
 /// `clone_into` with a reference will resolve the reference into a revision,
-/// and return a `CargoError` if no revision for that reference was found.
+/// and return a `failure::Error` if no revision for that reference was found.
 #[derive(Serialize)]
 pub struct GitCheckout<'a> {
     database: &'a GitDatabase,
@@ -587,7 +587,7 @@ where
     // In the case of an authentication failure (where we tried something) then
     // we try to give a more helpful error message about precisely what we
     // tried.
-    let res = res.map_err(CargoError::from).chain_err(|| {
+    let res = res.map_err(failure::Error::from).chain_err(|| {
         let mut msg = "failed to authenticate when downloading \
                        repository"
             .to_string();
diff --git a/src/cargo/util/cfg.rs b/src/cargo/util/cfg.rs
index 1dae93e3fd7..4e62605178d 100644
--- a/src/cargo/util/cfg.rs
+++ b/src/cargo/util/cfg.rs
@@ -2,7 +2,7 @@ use std::fmt;
 use std::iter;
 use std::str::{self, FromStr};
 
-use crate::util::{CargoError, CargoResult};
+use crate::util::CargoResult;
 
 #[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
 pub enum Cfg {
@@ -38,7 +38,7 @@ struct Parser<'a> {
 }
 
 impl FromStr for Cfg {
-    type Err = CargoError;
+    type Err = failure::Error;
 
     fn from_str(s: &str) -> CargoResult<Cfg> {
         let mut p = Parser::new(s);
@@ -85,7 +85,7 @@ impl CfgExpr {
 }
 
 impl FromStr for CfgExpr {
-    type Err = CargoError;
+    type Err = failure::Error;
 
     fn from_str(s: &str) -> CargoResult<CfgExpr> {
         let mut p = Parser::new(s);
diff --git a/src/cargo/util/errors.rs b/src/cargo/util/errors.rs
index 599396ebb71..168f7d8a83c 100644
--- a/src/cargo/util/errors.rs
+++ b/src/cargo/util/errors.rs
@@ -11,8 +11,7 @@ use log::trace;
 
 use crate::core::{TargetKind, Workspace};
 
-pub use failure::Error as CargoError;
-pub type CargoResult<T> = Result<T, Error>;
+pub type CargoResult<T> = failure::Fallible<T>; // Alex's body isn't quite ready to give up "Result"
 
 pub trait CargoResultExt<T, E> {
     fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
@@ -232,13 +231,13 @@ pub type CliResult = Result<(), CliError>;
 
 #[derive(Debug)]
 pub struct CliError {
-    pub error: Option<CargoError>,
+    pub error: Option<failure::Error>,
     pub unknown: bool,
     pub exit_code: i32,
 }
 
 impl CliError {
-    pub fn new(error: CargoError, code: i32) -> CliError {
+    pub fn new(error: failure::Error, code: i32) -> CliError {
         let unknown = error.downcast_ref::<Internal>().is_some();
         CliError {
             error: Some(error),
@@ -256,8 +255,8 @@ impl CliError {
     }
 }
 
-impl From<CargoError> for CliError {
-    fn from(err: CargoError) -> CliError {
+impl From<failure::Error> for CliError {
+    fn from(err: failure::Error) -> CliError {
         CliError::new(err, 101)
     }
 }
@@ -342,10 +341,10 @@ pub fn process_error(
     }
 }
 
-pub fn internal<S: fmt::Display>(error: S) -> CargoError {
+pub fn internal<S: fmt::Display>(error: S) -> failure::Error {
     _internal(&error)
 }
 
-fn _internal(error: &dyn fmt::Display) -> CargoError {
+fn _internal(error: &dyn fmt::Display) -> failure::Error {
     Internal::new(format_err!("{}", error)).into()
 }
diff --git a/src/cargo/util/flock.rs b/src/cargo/util/flock.rs
index 98c784049e2..48bcd91bd7d 100644
--- a/src/cargo/util/flock.rs
+++ b/src/cargo/util/flock.rs
@@ -8,7 +8,7 @@ use fs2::{lock_contended_error, FileExt};
 use libc;
 use termcolor::Color::Cyan;
 
-use crate::util::errors::{CargoError, CargoResult, CargoResultExt};
+use crate::util::errors::{CargoResult, CargoResultExt};
 use crate::util::paths;
 use crate::util::Config;
 
@@ -303,7 +303,7 @@ fn acquire(
 
         Err(e) => {
             if e.raw_os_error() != lock_contended_error().raw_os_error() {
-                let e = CargoError::from(e);
+                let e = failure::Error::from(e);
                 let cx = format!("failed to lock file: {}", path.display());
                 return Err(e.context(cx).into());
             }
diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs
index 74c6335cb89..598a94b2f77 100644
--- a/src/cargo/util/mod.rs
+++ b/src/cargo/util/mod.rs
@@ -5,7 +5,7 @@ pub use self::config::{homedir, Config, ConfigValue};
 pub use self::dependency_queue::{DependencyQueue, Dirty, Fresh, Freshness};
 pub use self::diagnostic_server::RustfixDiagnosticServer;
 pub use self::errors::{internal, process_error};
-pub use self::errors::{CargoError, CargoResult, CargoResultExt, CliResult, Test};
+pub use self::errors::{CargoResult, CargoResultExt, CliResult, Test};
 pub use self::errors::{CargoTestError, CliError, ProcessError};
 pub use self::flock::{FileLock, Filesystem};
 pub use self::graph::Graph;
diff --git a/src/cargo/util/network.rs b/src/cargo/util/network.rs
index cdf98929cb5..310f24a6550 100644
--- a/src/cargo/util/network.rs
+++ b/src/cargo/util/network.rs
@@ -108,20 +108,18 @@ fn with_retry_repeats_the_call_then_works() {
 
 #[test]
 fn with_retry_finds_nested_spurious_errors() {
-    use crate::util::CargoError;
-
     //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry
     //String error messages are not considered spurious
-    let error1 = CargoError::from(HttpNot200 {
+    let error1 = failure::Error::from(HttpNot200 {
         code: 501,
         url: "Uri".to_string(),
     });
-    let error1 = CargoError::from(error1.context("A non-spurious wrapping err"));
-    let error2 = CargoError::from(HttpNot200 {
+    let error1 = failure::Error::from(error1.context("A non-spurious wrapping err"));
+    let error2 = failure::Error::from(HttpNot200 {
         code: 502,
         url: "Uri".to_string(),
     });
-    let error2 = CargoError::from(error2.context("A second chained error"));
+    let error2 = failure::Error::from(error2.context("A second chained error"));
     let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
     let config = Config::default().unwrap();
     let result = with_retry(&config, || results.pop().unwrap());
diff --git a/src/cargo/util/paths.rs b/src/cargo/util/paths.rs
index f99f05c62f0..d40d6ea141c 100644
--- a/src/cargo/util/paths.rs
+++ b/src/cargo/util/paths.rs
@@ -8,7 +8,7 @@ use std::path::{Component, Path, PathBuf};
 
 use filetime::FileTime;
 
-use crate::util::errors::{CargoError, CargoResult, CargoResultExt, Internal};
+use crate::util::errors::{CargoResult, CargoResultExt, Internal};
 
 pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> CargoResult<OsString> {
     let err = match env::join_paths(paths.iter()) {
@@ -16,9 +16,9 @@ pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> CargoResult<OsStri
         Err(e) => e,
     };
     let paths = paths.iter().map(Path::new).collect::<Vec<_>>();
-    let err = CargoError::from(err);
+    let err = failure::Error::from(err);
     let explain = Internal::new(format_err!("failed to join path array: {:?}", paths));
-    let err = CargoError::from(err.context(explain));
+    let err = failure::Error::from(err.context(explain));
     let more_explain = format!(
         "failed to join search paths together\n\
          Does ${} have an unterminated quote character?",
diff --git a/src/cargo/util/process_builder.rs b/src/cargo/util/process_builder.rs
index a81a2af06ba..1cd2b708479 100644
--- a/src/cargo/util/process_builder.rs
+++ b/src/cargo/util/process_builder.rs
@@ -328,7 +328,7 @@ mod imp {
     pub fn exec_replace(process_builder: &ProcessBuilder) -> CargoResult<()> {
         let mut command = process_builder.build_command();
         let error = command.exec();
-        Err(crate::util::CargoError::from(error)
+        Err(failure::Error::from(error)
             .context(process_error(
                 &format!("could not execute process {}", process_builder),
                 None,
diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs
index 7ea3f06517a..898fc72fc48 100644
--- a/src/cargo/util/toml/mod.rs
+++ b/src/cargo/util/toml/mod.rs
@@ -19,7 +19,7 @@ use crate::core::{Dependency, Manifest, PackageId, Summary, Target};
 use crate::core::{Edition, EitherManifest, Feature, Features, VirtualManifest};
 use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRootConfig};
 use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY};
-use crate::util::errors::{CargoError, CargoResult, CargoResultExt, ManifestError};
+use crate::util::errors::{CargoResult, CargoResultExt, ManifestError};
 use crate::util::paths;
 use crate::util::{self, Config, ToUrl};
 
@@ -142,7 +142,7 @@ in the future.",
         return Ok(ret);
     }
 
-    let first_error = CargoError::from(first_error);
+    let first_error = failure::Error::from(first_error);
     Err(first_error.context("could not parse input as TOML").into())
 }
 
diff --git a/tests/testsuite/config.rs b/tests/testsuite/config.rs
index 714de310413..a15cae35b54 100644
--- a/tests/testsuite/config.rs
+++ b/tests/testsuite/config.rs
@@ -6,7 +6,6 @@ use crate::support::{lines_match, paths, project};
 use cargo::core::{enable_nightly_features, Shell};
 use cargo::util::config::{self, Config};
 use cargo::util::toml::{self, VecStringOrBool as VSOB};
-use cargo::CargoError;
 use serde::Deserialize;
 
 #[test]
@@ -69,7 +68,7 @@ fn new_config(env: &[(&str, &str)]) -> Config {
     config
 }
 
-fn assert_error<E: Borrow<CargoError>>(error: E, msgs: &str) {
+fn assert_error<E: Borrow<failure::Error>>(error: E, msgs: &str) {
     let causes = error
         .borrow()
         .iter_chain()