From b138286e2c16b4d940bf04c9ae78d610fafe7eca Mon Sep 17 00:00:00 2001
From: Stefan Junker <mail@stefanjunker.de>
Date: Wed, 3 Jun 2020 19:08:38 +0200
Subject: [PATCH] Replace failure crate with anyhow+thiserror

Failure was [deprecated][0] and suggests anyhow+thiserror to replace
itself in dependent projects.

[0]: https://github.com/rust-lang-nursery/failure/pull/347
---
 Cargo.lock                                    | 68 ++++++++++------
 cincinnati/Cargo.toml                         |  1 -
 cincinnati/src/lib.rs                         | 13 ++--
 cincinnati/src/plugins/catalog.rs             |  2 +-
 cincinnati/src/plugins/external/web.rs        |  2 +-
 .../internal/cincinnati_graph_fetch.rs        |  6 +-
 .../src/plugins/internal/edge_add_remove.rs   |  1 -
 .../plugin.rs                                 | 12 +--
 .../plugin.rs                                 |  2 +-
 .../plugins/internal/graph_builder/release.rs |  6 +-
 .../release_scrape_dockerv2/plugin.rs         |  4 +-
 .../release_scrape_dockerv2/registry/mod.rs   |  4 +-
 .../registry/network_tests.rs                 |  2 +-
 .../src/plugins/internal/node_remove.rs       |  1 -
 cincinnati/src/plugins/macros.rs              |  4 +-
 cincinnati/src/plugins/mod.rs                 | 15 ++--
 commons/Cargo.toml                            |  3 +-
 commons/src/config.rs                         |  2 +-
 commons/src/errors.rs                         | 35 ++++++---
 commons/src/lib.rs                            |  9 ++-
 commons/src/metrics.rs                        | 21 +++--
 commons/src/testing.rs                        |  4 +-
 e2e/tests/e2e.rs                              |  2 +-
 e2e/tests/prometheus_query.rs                 |  2 +-
 graph-builder/Cargo.toml                      |  1 -
 graph-builder/src/config/cli.rs               |  2 +-
 graph-builder/src/config/file.rs              |  2 +-
 graph-builder/src/config/options.rs           |  4 +-
 graph-builder/src/config/settings.rs          |  4 +-
 graph-builder/src/graph.rs                    |  5 +-
 graph-builder/src/lib.rs                      |  2 -
 graph-builder/src/main.rs                     |  5 +-
 graph-builder/src/status.rs                   | 17 ++--
 policy-engine/Cargo.toml                      |  1 -
 policy-engine/src/config/cli.rs               |  2 +-
 policy-engine/src/config/file.rs              |  4 +-
 policy-engine/src/config/options.rs           |  4 +-
 policy-engine/src/config/settings.rs          |  2 +-
 policy-engine/src/graph.rs                    | 78 +++++++++----------
 policy-engine/src/main.rs                     |  4 +-
 policy-engine/src/openapi.rs                  | 32 ++++----
 prometheus-query/Cargo.toml                   |  2 +-
 prometheus-query/src/lib.rs                   |  2 -
 prometheus-query/src/v1/mod.rs                |  2 +-
 prometheus-query/src/v1/queries/instant.rs    |  2 +-
 prometheus-query/src/v1/queries/mod.rs        |  2 +-
 quay/Cargo.toml                               |  4 +-
 quay/src/lib.rs                               |  5 +-
 quay/src/v1/manifest.rs                       |  2 +-
 quay/src/v1/mod.rs                            |  2 +-
 quay/src/v1/tag.rs                            |  2 +-
 quay/tests/net/private.rs                     |  3 +-
 52 files changed, 211 insertions(+), 207 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 4d0b9f1ae..d300bbeb7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -108,7 +108,7 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -264,7 +264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -274,7 +274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -365,7 +365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -375,7 +375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -619,7 +619,6 @@ dependencies = [
  "daggy 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dkregistry 0.4.0-alpha.0 (git+https://github.com/camallo/dkregistry-rs.git?rev=712f7dae50068948e8678af535ce90bb63afd878)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures-locks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -687,8 +686,8 @@ name = "commons"
 version = "0.1.0"
 dependencies = [
  "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -696,6 +695,7 @@ dependencies = [
  "prometheus 0.7.0 (git+https://github.com/pingcap/rust-prometheus.git?rev=6a02b0d2943f8fffce672e236e22c6f925184d93)",
  "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "twoway 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -845,7 +845,7 @@ version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -874,7 +874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -976,7 +976,7 @@ dependencies = [
  "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1163,7 +1163,7 @@ dependencies = [
  "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1245,7 +1245,6 @@ dependencies = [
  "commons 0.1.0",
  "custom_debug_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1964,7 +1963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1993,7 +1992,6 @@ dependencies = [
  "commons 0.1.0",
  "custom_debug_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2060,7 +2058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2101,10 +2099,10 @@ dependencies = [
 name = "prometheus-query"
 version = "0.0.0-dev"
 dependencies = [
+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "commons 0.1.0",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2164,9 +2162,9 @@ dependencies = [
 name = "quay"
 version = "0.0.0-dev"
 dependencies = [
+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2583,7 +2581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2762,7 +2760,7 @@ dependencies = [
  "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2777,7 +2775,7 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.5"
+version = "1.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2850,7 +2848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2862,6 +2860,24 @@ dependencies = [
  "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "thiserror"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "thread_local"
 version = "1.0.1"
@@ -3346,7 +3362,7 @@ dependencies = [
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3377,7 +3393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3397,7 +3413,7 @@ dependencies = [
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3798,7 +3814,7 @@ dependencies = [
 "checksum strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "572a2f4e53dd4c3483fd79e5cc10ddd773a3acb1169bbfe8762365e107110579"
 "checksum strum_macros 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6e163a520367c465f59e0a61a23cfae3b10b6546d78b6f672a382be79f7110"
 "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
-"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
+"checksum syn 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060"
 "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
 "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
 "checksum tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "b3196bfbffbba3e57481b6ea32249fbaf590396a52505a2615adbb79d9d826d3"
@@ -3807,6 +3823,8 @@ dependencies = [
 "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
 "checksum test-case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "199464148b42bcf3da8b2a56f6ee87ca68f47402496d1268849291ec9fb463c8"
 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+"checksum thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
+"checksum thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
 "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
 "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
diff --git a/cincinnati/Cargo.toml b/cincinnati/Cargo.toml
index 36590961a..d51f18398 100644
--- a/cincinnati/Cargo.toml
+++ b/cincinnati/Cargo.toml
@@ -10,7 +10,6 @@ commons = { path = "../commons" }
 custom_debug_derive = "^0.1.7"
 daggy = { version = "^0.6.0", features = [ "serde-1" ] }
 env_logger = "^0.6.0"
-failure = "^0.1.1"
 futures = "0.3"
 futures-locks = "0.5.0"
 lazy_static = "^1.2.0"
diff --git a/cincinnati/src/lib.rs b/cincinnati/src/lib.rs
index edc4f6dc3..52b0c7e36 100644
--- a/cincinnati/src/lib.rs
+++ b/cincinnati/src/lib.rs
@@ -12,18 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#[macro_use]
-extern crate failure;
-
 #[macro_use]
 extern crate serde_derive;
 
 #[macro_use]
 pub mod plugins;
 
+use commons::prelude_errors::*;
 use daggy::petgraph::visit::{IntoNodeReferences, NodeRef};
 use daggy::{Dag, EdgeIndex, Walker};
-use failure::{Error, Fallible};
 use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 use std::{collections, fmt};
@@ -154,9 +151,11 @@ pub struct Empty;
 
 /// Errors that can be returned by the methods in this library
 pub mod errors {
+    use commons::prelude_errors::*;
+
     /// Edge already exists
     #[derive(Debug, Fail, Eq, PartialEq)]
-    #[fail(display = "edge from {:?} to {:?} already exists", from, to)]
+    #[error("edge from {:?} to {:?} already exists", from, to)]
     pub struct EdgeAlreadyExists {
         pub(crate) from: String,
         pub(crate) to: String,
@@ -164,7 +163,7 @@ pub mod errors {
 
     /// Edge doesn't exist
     #[derive(Debug, Fail, Eq, PartialEq)]
-    #[fail(display = "edge from '{:?}' to '{:?}' doesn't exist", from, to)]
+    #[error("edge from '{:?}' to '{:?}' doesn't exist", from, to)]
     pub struct EdgeDoesntExist {
         pub(crate) from: String,
         pub(crate) to: String,
@@ -172,7 +171,7 @@ pub mod errors {
 
     /// Missing node weight
     #[derive(Debug, Fail, Eq, PartialEq)]
-    #[fail(display = "NodeWeight with index {} is missing", 0)]
+    #[error("NodeWeight with index {} is missing", 0)]
     pub struct NodeWeightMissing(pub(crate) usize);
 }
 
diff --git a/cincinnati/src/plugins/catalog.rs b/cincinnati/src/plugins/catalog.rs
index 15560a77a..ff67d3567 100644
--- a/cincinnati/src/plugins/catalog.rs
+++ b/cincinnati/src/plugins/catalog.rs
@@ -22,7 +22,7 @@ use super::internal::openshift_secondary_metadata_parser::{
 use super::internal::release_scrape_dockerv2::{
     ReleaseScrapeDockerv2Plugin, ReleaseScrapeDockerv2Settings,
 };
-use failure::{bail, format_err, Fallible};
+use commons::prelude_errors::*;
 use std::fmt::Debug;
 
 /// Key used to look up plugin-type in a configuration entry.
diff --git a/cincinnati/src/plugins/external/web.rs b/cincinnati/src/plugins/external/web.rs
index 136bf9e93..383d0456d 100644
--- a/cincinnati/src/plugins/external/web.rs
+++ b/cincinnati/src/plugins/external/web.rs
@@ -20,8 +20,8 @@ mod tests {
     use async_trait::async_trait;
     use cincinnati::plugins::{interface, ExternalIO, ExternalPlugin, InternalIO, PluginResult};
     use cincinnati::testing::generate_graph;
+    use commons::prelude_errors::*;
     use commons::testing::init_runtime;
-    use failure::Fallible;
     use log::trace;
     use std::convert::TryInto;
 
diff --git a/cincinnati/src/plugins/internal/cincinnati_graph_fetch.rs b/cincinnati/src/plugins/internal/cincinnati_graph_fetch.rs
index 29920dce1..8e92d3612 100644
--- a/cincinnati/src/plugins/internal/cincinnati_graph_fetch.rs
+++ b/cincinnati/src/plugins/internal/cincinnati_graph_fetch.rs
@@ -9,8 +9,8 @@ use self::cincinnati::plugins::prelude::*;
 use self::cincinnati::plugins::prelude_plugin_impl::*;
 use self::cincinnati::CONTENT_TYPE;
 
+use commons::prelude_errors::*;
 use commons::GraphError;
-use failure::{Fallible, ResultExt};
 use prometheus::Counter;
 use reqwest;
 use reqwest::header::{HeaderValue, ACCEPT};
@@ -158,8 +158,8 @@ mod tests {
     use super::*;
     use cincinnati::testing::generate_custom_graph;
     use commons::metrics::{self, RegistryWrapper};
+    use commons::prelude_errors::*;
     use commons::testing::{self, init_runtime};
-    use failure::{bail, Fallible};
     use prometheus::Registry;
 
     macro_rules! fetch_upstream_success_test {
@@ -318,7 +318,7 @@ mod tests {
         let metrics_call = metrics::serve::<metrics::RegistryWrapper>(actix_web::web::Data::new(
             RegistryWrapper(registry),
         ));
-        let resp = rt.block_on(metrics_call)?;
+        let resp = rt.block_on(metrics_call);
 
         assert_eq!(resp.status(), 200);
         if let actix_web::body::ResponseBody::Body(body) = resp.body() {
diff --git a/cincinnati/src/plugins/internal/edge_add_remove.rs b/cincinnati/src/plugins/internal/edge_add_remove.rs
index 8672ce4f6..c1c41bb5a 100644
--- a/cincinnati/src/plugins/internal/edge_add_remove.rs
+++ b/cincinnati/src/plugins/internal/edge_add_remove.rs
@@ -333,7 +333,6 @@ mod tests {
     use cincinnati::testing::generate_custom_graph;
     use cincinnati::MapImpl;
     use commons::testing::init_runtime;
-    use failure::ResultExt;
 
     static KEY_PREFIX: &str = "test_key";
 
diff --git a/cincinnati/src/plugins/internal/graph_builder/github_openshift_secondary_metadata_scraper/plugin.rs b/cincinnati/src/plugins/internal/graph_builder/github_openshift_secondary_metadata_scraper/plugin.rs
index 4746f7a38..2b0f93f2a 100644
--- a/cincinnati/src/plugins/internal/graph_builder/github_openshift_secondary_metadata_scraper/plugin.rs
+++ b/cincinnati/src/plugins/internal/graph_builder/github_openshift_secondary_metadata_scraper/plugin.rs
@@ -44,7 +44,7 @@ impl Reference {
 }
 
 impl TryFrom<(Option<&String>, Option<&String>)> for Reference {
-    type Error = failure::Error;
+    type Error = Error;
 
     fn try_from(options: (Option<&String>, Option<&String>)) -> Fallible<Self> {
         let reference = match (options.0, options.1) {
@@ -194,7 +194,7 @@ impl GithubOpenshiftSecondaryMetadataScraperPlugin {
             reference: settings
                 .reference
                 .clone()
-                .ok_or_else(|| failure::err_msg("settings don't contain a 'reference'"))?,
+                .ok_or_else(|| format_err!("settings don't contain a 'reference'"))?,
             settings,
             output_whitelist,
             oauth_token,
@@ -248,7 +248,7 @@ impl GithubOpenshiftSecondaryMetadataScraperPlugin {
             })
             .nth(0)
             .ok_or_else(|| {
-                failure::err_msg(format!(
+                format_err!(format!(
                     "{}/{} does not have branch {}: {:#?}",
                     &self.settings.github_org,
                     &self.settings.github_repo,
@@ -304,7 +304,7 @@ impl GithubOpenshiftSecondaryMetadataScraperPlugin {
             state
                 .commit_wanted
                 .clone()
-                .ok_or_else(|| failure::err_msg("commit_wanted unset"))?
+                .ok_or_else(|| format_err!("commit_wanted unset"))?
         };
 
         let url = github_v3::tarball_url(
@@ -371,7 +371,7 @@ impl GithubOpenshiftSecondaryMetadataScraperPlugin {
                                 &entry.header().clone().path().unwrap_or_default()
                             ))?
                             .to_str()
-                            .ok_or_else(|| failure::err_msg("Could not get string from entry"))?
+                            .ok_or_else(|| format_err!("Could not get string from entry"))?
                             .to_owned();
                         trace!("Processing entry with path {:?}", &path);
 
@@ -450,7 +450,7 @@ impl InternalPlugin for GithubOpenshiftSecondaryMetadataScraperPlugin {
             self.data_dir
                 .path()
                 .to_str()
-                .ok_or_else(|| failure::err_msg("data_dir cannot be converted to str"))?
+                .ok_or_else(|| format_err!("data_dir cannot be converted to str"))?
                 .to_string(),
         );
 
diff --git a/cincinnati/src/plugins/internal/graph_builder/openshift_secondary_metadata_parser/plugin.rs b/cincinnati/src/plugins/internal/graph_builder/openshift_secondary_metadata_parser/plugin.rs
index 3bcaf52d4..5913ad7ff 100644
--- a/cincinnati/src/plugins/internal/graph_builder/openshift_secondary_metadata_parser/plugin.rs
+++ b/cincinnati/src/plugins/internal/graph_builder/openshift_secondary_metadata_parser/plugin.rs
@@ -492,7 +492,7 @@ mod tests {
     use self::cincinnati::plugins::InternalPlugin;
     use self::cincinnati::testing::compare_graphs_verbose;
 
-    use failure::{Fallible, ResultExt};
+    use commons::prelude_errors::*;
     use std::path::PathBuf;
     use std::str::FromStr;
     use test_case::test_case;
diff --git a/cincinnati/src/plugins/internal/graph_builder/release.rs b/cincinnati/src/plugins/internal/graph_builder/release.rs
index a9e0267ca..7b423bbc2 100644
--- a/cincinnati/src/plugins/internal/graph_builder/release.rs
+++ b/cincinnati/src/plugins/internal/graph_builder/release.rs
@@ -16,7 +16,7 @@ use crate as cincinnati;
 
 use self::cincinnati::MapImpl;
 
-use failure::Fallible;
+use commons::prelude_errors::*;
 use itertools::Itertools;
 use log::{trace, warn};
 use semver::Version;
@@ -75,7 +75,7 @@ pub enum MetadataKind {
 ///
 /// When processing previous/next release metadata it is assumed that the edge
 /// destination has the same build type as the origin.
-pub fn create_graph(releases: Vec<Release>) -> Result<cincinnati::Graph, failure::Error> {
+pub fn create_graph(releases: Vec<Release>) -> Result<cincinnati::Graph, Error> {
     let mut graph = cincinnati::Graph::default();
 
     releases
@@ -146,7 +146,7 @@ pub fn create_graph(releases: Vec<Release>) -> Result<cincinnati::Graph, failure
                     if let Err(e) = graph.add_edge(&&current, &next) {
                         if let Some(eae) = e.downcast_ref::<cincinnati::errors::EdgeAlreadyExists>()
                         {
-                            warn!("{}", eae);
+                            warn!("{:?}", eae);
                         } else {
                             return Err(e);
                         }
diff --git a/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/plugin.rs b/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/plugin.rs
index 44549a451..485c2258c 100644
--- a/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/plugin.rs
+++ b/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/plugin.rs
@@ -98,7 +98,7 @@ impl ReleaseScrapeDockerv2Plugin {
         mut settings: ReleaseScrapeDockerv2Settings,
         cache: Option<registry::cache::Cache>,
         prometheus_registry: Option<&prometheus::Registry>,
-    ) -> failure::Fallible<Self> {
+    ) -> Fallible<Self> {
         use prometheus::IntGauge;
         let graph_upstream_raw_releases: IntGauge = IntGauge::new(
             "graph_upstream_raw_releases",
@@ -173,7 +173,7 @@ mod network_tests {
 
     use cincinnati::plugins::internal::graph_builder::commons::tests::common_init;
     use cincinnati::testing::{TestGraphBuilder, TestMetadata};
-    use failure::{Fallible, ResultExt};
+    use commons::prelude_errors::*;
     use std::collections::HashSet;
 
     #[test]
diff --git a/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/mod.rs b/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/mod.rs
index 45a978b4b..9bb393099 100644
--- a/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/mod.rs
+++ b/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/mod.rs
@@ -15,8 +15,8 @@
 use crate as cincinnati;
 
 use self::cincinnati::plugins::internal::graph_builder::release::Metadata;
+use self::cincinnati::plugins::prelude_plugin_impl::*;
 
-use failure::{bail, ensure, format_err, Error, Fallible, ResultExt};
 use flate2::read::GzDecoder;
 use futures::lock::Mutex as FuturesMutex;
 use futures::prelude::*;
@@ -385,7 +385,7 @@ async fn get_manifest_and_ref(
     tag: String,
     repo: String,
     authenticated_client: &dkregistry::v2::Client,
-) -> Result<(String, dkregistry::v2::manifest::Manifest, String), failure::Error> {
+) -> Result<(String, dkregistry::v2::manifest::Manifest, String), Error> {
     trace!("[{}] Processing {}", &tag, &repo);
     let (manifest, manifestref) = authenticated_client
         .get_manifest_and_ref(&repo, &tag)
diff --git a/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/network_tests.rs b/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/network_tests.rs
index 09ca7609e..3457b524e 100644
--- a/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/network_tests.rs
+++ b/cincinnati/src/plugins/internal/graph_builder/release_scrape_dockerv2/registry/network_tests.rs
@@ -11,7 +11,7 @@ use cincinnati::plugins::internal::graph_builder::release_scrape_dockerv2::regis
 };
 use cincinnati::plugins::internal::metadata_fetch_quay::DEFAULT_QUAY_MANIFESTREF_KEY as MANIFESTREF_KEY;
 use cincinnati::{Empty, MapImpl, WouldCycle};
-use failure::{bail, ensure, Fallible};
+use commons::prelude_errors::*;
 use itertools::Itertools;
 use semver::Version;
 use std::collections::HashMap;
diff --git a/cincinnati/src/plugins/internal/node_remove.rs b/cincinnati/src/plugins/internal/node_remove.rs
index 87943131f..95b17c63c 100644
--- a/cincinnati/src/plugins/internal/node_remove.rs
+++ b/cincinnati/src/plugins/internal/node_remove.rs
@@ -71,7 +71,6 @@ mod tests {
     use super::*;
     use cincinnati::testing::{generate_custom_graph, TestMetadata};
     use commons::testing::init_runtime;
-    use failure::ResultExt;
 
     #[test]
     fn ensure_release_remove() -> Fallible<()> {
diff --git a/cincinnati/src/plugins/macros.rs b/cincinnati/src/plugins/macros.rs
index 6ebe0d540..4300db116 100644
--- a/cincinnati/src/plugins/macros.rs
+++ b/cincinnati/src/plugins/macros.rs
@@ -9,7 +9,7 @@ macro_rules! get_multiple_values {
                     if let Some(value) = $map.get($key) {
                         value
                     } else {
-                        failure::bail!("{}", $key)
+                        return Err(Box::new(format!("{}", $key)));
                     },
                 )
             };
@@ -25,7 +25,7 @@ macro_rules! get_multiple_values {
                             if let Some(value) = $map.get($key) {
                                 value
                             } else {
-                                failure::bail!("{}", $key)
+                                return Err(Box::new(format!("{}", $key)));
                             },
                         )*
                     )
diff --git a/cincinnati/src/plugins/mod.rs b/cincinnati/src/plugins/mod.rs
index 2eb1c1831..215b1eb41 100644
--- a/cincinnati/src/plugins/mod.rs
+++ b/cincinnati/src/plugins/mod.rs
@@ -14,7 +14,7 @@ use crate as cincinnati;
 use self::cincinnati::plugins::interface::{PluginError, PluginExchange};
 
 use async_trait::async_trait;
-use failure::{Error, Fallible, ResultExt};
+pub use commons::prelude_errors::*;
 use std::collections::HashMap;
 use std::convert::{TryFrom, TryInto};
 use std::fmt::Debug;
@@ -45,6 +45,8 @@ pub mod prelude {
     };
 
     pub use std::iter::FromIterator;
+
+    pub use commons::prelude_errors::*;
 }
 
 pub mod prelude_plugin_impl {
@@ -56,8 +58,8 @@ pub mod prelude_plugin_impl {
     pub use plugins::{BoxedPlugin, InternalIO, InternalPlugin, InternalPluginWrapper};
 
     pub use async_trait::async_trait;
+    pub use commons::prelude_errors::*;
     pub use custom_debug_derive::CustomDebug;
-    pub use failure::{bail, ensure, Fallible, ResultExt};
     pub use futures::TryFutureExt;
     pub use log::{debug, error, info, trace, warn};
     pub use serde::{de::DeserializeOwned, Deserialize};
@@ -89,7 +91,7 @@ pub enum PluginIO {
 /// Error type which corresponds to interface::PluginError
 #[derive(Debug, Fail)]
 pub enum ExternalError {
-    #[fail(display = "PluginError: {:?}", 0)]
+    #[error("PluginError: {:?}", 0)]
     PluginError(PluginError),
 }
 
@@ -406,7 +408,7 @@ where
                     "Processing all plugins with a timeout of {:?}",
                     timeout
                 ))
-                .map_err(failure::Error::from)
+                .map_err(Error::from)
                 .unwrap_or_else(Err);
 
             // This may fail if it's attempted after the timeout is exceeded.
@@ -418,10 +420,7 @@ where
         std::thread::sleep(deadline);
 
         // This may fail if it's attempted after processing is finished.
-        let _ = tx.send(Err(failure::err_msg(format!(
-            "Exceeded timeout of {:?}",
-            &timeout
-        ))));
+        let _ = tx.send(Err(format_err!("Exceeded timeout of {:?}", &timeout)));
     });
 
     rx.recv()?
diff --git a/commons/Cargo.toml b/commons/Cargo.toml
index e188b7a29..a3f87410c 100644
--- a/commons/Cargo.toml
+++ b/commons/Cargo.toml
@@ -7,7 +7,8 @@ edition = "2018"
 [dependencies]
 actix-web = "^2.0"
 env_logger = "^0.6.0"
-failure = "^0.1.5"
+anyhow = "1.0"
+thiserror = "1.0"
 lazy_static = "^1.2.0"
 log = "^0.4.6"
 prometheus = { git = "https://github.com/pingcap/rust-prometheus.git", rev = "6a02b0d2943f8fffce672e236e22c6f925184d93"}
diff --git a/commons/src/config.rs b/commons/src/config.rs
index bb91575c4..8d08a1c9d 100644
--- a/commons/src/config.rs
+++ b/commons/src/config.rs
@@ -20,5 +20,5 @@ macro_rules! assign_if_some {
 /// leaving unset ones preserved as-is from existing settings.
 pub trait MergeOptions<T> {
     /// MergeOptions values from `options` into current settings.
-    fn try_merge(&mut self, options: T) -> failure::Fallible<()>;
+    fn try_merge(&mut self, options: T) -> crate::Fallible<()>;
 }
diff --git a/commons/src/errors.rs b/commons/src/errors.rs
index 74c5ccecf..deab67827 100644
--- a/commons/src/errors.rs
+++ b/commons/src/errors.rs
@@ -1,7 +1,20 @@
 use actix_web::http;
 use actix_web::HttpResponse;
-use failure::Fallible;
 use prometheus::{IntCounterVec, Opts, Registry};
+use thiserror::Error;
+
+pub mod prelude {
+    pub use anyhow::anyhow as format_err;
+    pub use anyhow::bail;
+    pub use anyhow::ensure;
+    pub use anyhow::Context;
+    pub use anyhow::Error;
+    pub use anyhow::Result as Fallible;
+
+    // Macro imports
+    pub use thiserror::Error as Fail;
+}
+pub use prelude::*;
 
 lazy_static! {
     static ref V1_GRAPH_ERRORS: IntCounterVec = IntCounterVec::new(
@@ -25,43 +38,43 @@ pub fn register_metrics(registry: &Registry) -> Fallible<()> {
     Ok(())
 }
 
-#[derive(Debug, Fail, Eq, PartialEq)]
+#[derive(Debug, Error, Eq, PartialEq)]
 /// Error that can be returned by `/v1/graph` endpoint.
 pub enum GraphError {
     /// Failed to deserialize JSON.
-    #[fail(display = "failed to deserialize JSON: {}", _0)]
+    #[error("failed to deserialize JSON: {}", _0)]
     FailedJsonIn(String),
 
     /// Failed to serialize JSON.
-    #[fail(display = "failed to serialize JSON: {}", _0)]
+    #[error("failed to serialize JSON: {}", _0)]
     FailedJsonOut(String),
 
     /// Error response from upstream.
-    #[fail(display = "failed to fetch upstream graph: {}", _0)]
+    #[error("failed to fetch upstream graph: {}", _0)]
     FailedUpstreamFetch(String),
 
     /// Plugin failure.
-    #[fail(display = "failed to execute plugins: {}", _0)]
+    #[error("failed to execute plugins: {}", _0)]
     FailedPluginExecution(String),
 
     /// Error while reaching upstream.
-    #[fail(display = "failed to assemble upstream request")]
+    #[error("failed to assemble upstream request")]
     FailedUpstreamRequest(String),
 
     /// Requested invalid mediatype.
-    #[fail(display = "invalid Content-Type requested")]
+    #[error("invalid Content-Type requested")]
     InvalidContentType,
 
     /// Missing client parameters.
-    #[fail(display = "mandatory client parameters missing")]
+    #[error("mandatory client parameters missing")]
     MissingParams(Vec<String>),
 
     /// Invalid client parameters.
-    #[fail(display = "invalid client parameters: {}", _0)]
+    #[error("invalid client parameters: {}", _0)]
     InvalidParams(String),
 
     /// Failed to parse as Semantic Version
-    #[fail(display = "failed to process version: {}", _0)]
+    #[error("failed to process version: {}", _0)]
     ArchVersionError(String),
 }
 
diff --git a/commons/src/lib.rs b/commons/src/lib.rs
index d884385e2..71f9e59e4 100644
--- a/commons/src/lib.rs
+++ b/commons/src/lib.rs
@@ -4,8 +4,6 @@
 
 extern crate actix_web;
 #[macro_use]
-extern crate failure;
-#[macro_use]
 extern crate lazy_static;
 #[macro_use]
 extern crate serde_json;
@@ -18,7 +16,12 @@ pub mod metrics;
 pub mod testing;
 
 mod errors;
-pub use errors::{register_metrics, GraphError, MISSING_APPSTATE_PANIC_MSG};
+pub use errors::{register_metrics, Fallible, GraphError, MISSING_APPSTATE_PANIC_MSG};
+
+/// Commonly used imports for error handling.
+pub mod prelude_errors {
+    pub use crate::errors::prelude::*;
+}
 
 use actix_web::http::header;
 use std::collections::HashSet;
diff --git a/commons/src/metrics.rs b/commons/src/metrics.rs
index 551514a46..f41b6e5fb 100644
--- a/commons/src/metrics.rs
+++ b/commons/src/metrics.rs
@@ -1,7 +1,7 @@
 //! Metrics service.
 
+use crate::prelude_errors::*;
 use actix_web::HttpResponse;
-use failure::Fallible;
 use prometheus::{self, Registry};
 
 /// For types that store a static Registry reference
@@ -20,26 +20,25 @@ impl HasRegistry for RegistryWrapper {
 }
 
 /// Serve metrics requests (Prometheus textual format).
-pub async fn serve<T>(app_data: actix_web::web::Data<T>) -> Fallible<HttpResponse>
+pub async fn serve<T>(app_data: actix_web::web::Data<T>) -> HttpResponse
 where
     T: 'static + HasRegistry,
 {
     use prometheus::Encoder;
 
     let metrics = app_data.registry().gather();
-    let content = {
-        let tenc = prometheus::TextEncoder::new();
-        let mut buf = vec![];
-        tenc.encode(&metrics, &mut buf).and(Ok(buf))?
-    };
-
-    Ok(HttpResponse::Ok().body(content))
+    let tenc = prometheus::TextEncoder::new();
+    let mut buf = vec![];
+    match tenc.encode(&metrics, &mut buf) {
+        Ok(()) => HttpResponse::Ok().body(buf),
+        Err(e) => HttpResponse::InternalServerError().message_body(format!("{}", e).into()),
+    }
 }
 
 /// Create a custom Prometheus registry.
 pub fn new_registry(prefix: Option<String>) -> Fallible<Registry> {
     Registry::new_custom(prefix.clone(), None).map_err(|e| {
-        failure::err_msg(format!(
+        format_err!(format!(
             "could not create a custom regostry with prefix {:?}: {}",
             prefix,
             e.to_string()
@@ -64,7 +63,7 @@ mod tests {
         testing::dummy_gauge(&registry_wrapped.0, 42.0)?;
 
         let metrics_call = serve::<RegistryWrapper>(actix_web::web::Data::new(registry_wrapped));
-        let resp = rt.block_on(metrics_call)?;
+        let resp = rt.block_on(metrics_call);
 
         assert_eq!(resp.status(), 200);
         if let actix_web::body::ResponseBody::Body(body) = resp.body() {
diff --git a/commons/src/testing.rs b/commons/src/testing.rs
index 592d9d967..df62d3b16 100644
--- a/commons/src/testing.rs
+++ b/commons/src/testing.rs
@@ -1,6 +1,6 @@
 //! Test helpers.
 
-use failure::Fallible;
+use crate::prelude_errors::*;
 use tokio::runtime::Runtime;
 
 /// Initialize logging.
@@ -12,7 +12,7 @@ pub fn init_logger() -> Fallible<()> {
 /// Initialize a tokio runtime for tests, with logging.
 pub fn init_runtime() -> Fallible<Runtime> {
     let _ = init_logger();
-    Runtime::new().map_err(failure::Error::from)
+    Runtime::new().map_err(Error::from)
 }
 
 /// Register a dummy gauge, with given value.
diff --git a/e2e/tests/e2e.rs b/e2e/tests/e2e.rs
index 3dbbd0558..9f4dd481c 100644
--- a/e2e/tests/e2e.rs
+++ b/e2e/tests/e2e.rs
@@ -1,4 +1,4 @@
-use failure::ResultExt;
+use commons::prelude_errors::*;
 use reqwest::header::{HeaderValue, ACCEPT};
 use std::env;
 use test_case::test_case;
diff --git a/e2e/tests/prometheus_query.rs b/e2e/tests/prometheus_query.rs
index 9ddfbcee4..73d2d39e4 100644
--- a/e2e/tests/prometheus_query.rs
+++ b/e2e/tests/prometheus_query.rs
@@ -1,4 +1,4 @@
-use failure::{Fallible, ResultExt};
+use commons::prelude_errors::*;
 use prometheus_query::v1::queries::{QueryData, QueryResult, VectorResult};
 use prometheus_query::v1::Client;
 
diff --git a/graph-builder/Cargo.toml b/graph-builder/Cargo.toml
index 1f2340b69..b4f5125fa 100644
--- a/graph-builder/Cargo.toml
+++ b/graph-builder/Cargo.toml
@@ -12,7 +12,6 @@ chrono = "^0.4.7"
 cincinnati = { path = "../cincinnati" }
 commons = { path = "../commons" }
 env_logger = "^0.6.0"
-failure = "^0.1.1"
 flate2 = "^1.0.1"
 futures = "0.3"
 itertools = "^0.8.2"
diff --git a/graph-builder/src/config/cli.rs b/graph-builder/src/config/cli.rs
index 2d288f34f..d33a89735 100644
--- a/graph-builder/src/config/cli.rs
+++ b/graph-builder/src/config/cli.rs
@@ -2,8 +2,8 @@
 
 use super::options;
 use super::AppSettings;
+use commons::prelude_errors::*;
 use commons::MergeOptions;
-use failure::Fallible;
 
 /// CLI configuration flags, top-level.
 #[derive(Debug, StructOpt)]
diff --git a/graph-builder/src/config/file.rs b/graph-builder/src/config/file.rs
index fcbb0d28f..d1e21647b 100644
--- a/graph-builder/src/config/file.rs
+++ b/graph-builder/src/config/file.rs
@@ -3,8 +3,8 @@
 use super::options;
 use super::AppSettings;
 use commons::de::de_loglevel;
+use commons::prelude_errors::*;
 use commons::MergeOptions;
-use failure::{Fallible, ResultExt};
 use std::io::Read;
 use std::{fs, io, path};
 
diff --git a/graph-builder/src/config/options.rs b/graph-builder/src/config/options.rs
index 2aef54e40..bc8c7b752 100644
--- a/graph-builder/src/config/options.rs
+++ b/graph-builder/src/config/options.rs
@@ -1,8 +1,8 @@
 //! Options shared by CLI and TOML.
 
 use super::AppSettings;
+use commons::prelude_errors::*;
 use commons::{de_path_prefix, parse_params_set, parse_path_prefix, MergeOptions};
-use failure::Fallible;
 use std::collections::HashSet;
 use std::net::IpAddr;
 use std::path::PathBuf;
@@ -138,7 +138,7 @@ where
     Ok(Some(Duration::from_secs(secs)))
 }
 
-pub fn duration_from_secs<S>(num: S) -> failure::Fallible<Duration>
+pub fn duration_from_secs<S>(num: S) -> Fallible<Duration>
 where
     S: AsRef<str>,
 {
diff --git a/graph-builder/src/config/settings.rs b/graph-builder/src/config/settings.rs
index 84d01bf31..56a83fe0d 100644
--- a/graph-builder/src/config/settings.rs
+++ b/graph-builder/src/config/settings.rs
@@ -3,8 +3,8 @@
 use super::{cli, file};
 use cincinnati::plugins::catalog::{build_plugins, PluginSettings};
 use cincinnati::plugins::BoxedPlugin;
+use commons::prelude_errors::*;
 use commons::MergeOptions;
-use failure::Fallible;
 use std::collections::HashSet;
 use std::net::{IpAddr, Ipv4Addr};
 use std::path::PathBuf;
@@ -125,8 +125,6 @@ impl AppSettings {
     }
 
     fn default_openshift_plugin_settings(&self) -> Fallible<Vec<Box<dyn PluginSettings>>> {
-        use failure::ResultExt;
-
         use cincinnati::plugins::internal::github_openshift_secondary_metadata_scraper::GITHUB_SCRAPER_TOKEN_PATH_ENV;
         use cincinnati::plugins::prelude::*;
 
diff --git a/graph-builder/src/graph.rs b/graph-builder/src/graph.rs
index d0131cd04..1d27e595b 100644
--- a/graph-builder/src/graph.rs
+++ b/graph-builder/src/graph.rs
@@ -18,8 +18,7 @@ use actix_web::{HttpRequest, HttpResponse};
 use cincinnati::plugins::prelude::*;
 use cincinnati::CONTENT_TYPE;
 use commons::metrics::HasRegistry;
-use commons::GraphError;
-use failure::Fallible;
+use commons::{Fallible, GraphError};
 use lazy_static;
 pub use parking_lot::RwLock;
 use prometheus::{self, histogram_opts, labels, opts, Counter, Gauge, Histogram, IntGauge};
@@ -207,7 +206,7 @@ pub fn run(settings: &config::AppSettings, state: &State) -> ! {
             Ok(internal_io) => internal_io,
             Err(err) => {
                 UPSTREAM_ERRORS.inc();
-                err.iter_chain().for_each(|cause| error!("{}", cause));
+                err.chain().for_each(|cause| error!("{}", cause));
                 continue;
             }
         };
diff --git a/graph-builder/src/lib.rs b/graph-builder/src/lib.rs
index 2f3141833..b5bfac933 100644
--- a/graph-builder/src/lib.rs
+++ b/graph-builder/src/lib.rs
@@ -1,8 +1,6 @@
 #[macro_use]
 extern crate commons;
 #[macro_use]
-extern crate failure;
-#[macro_use]
 extern crate lazy_static;
 #[macro_use]
 extern crate log;
diff --git a/graph-builder/src/main.rs b/graph-builder/src/main.rs
index c4f1b5bea..0a95466af 100644
--- a/graph-builder/src/main.rs
+++ b/graph-builder/src/main.rs
@@ -14,7 +14,7 @@
 
 use actix_web::{middleware, App, HttpServer};
 use commons::metrics::{self, HasRegistry};
-use failure::{ensure, Error, Fallible, ResultExt};
+use commons::prelude_errors::*;
 use graph_builder::{self, config, graph, status};
 use log::debug;
 use parking_lot::RwLock;
@@ -145,7 +145,6 @@ mod tests {
     use commons::metrics::HasRegistry;
     use commons::metrics::RegistryWrapper;
     use commons::testing;
-    use failure::{bail, Fallible};
     use parking_lot::RwLock;
     use prometheus::Registry;
     use std::collections::HashSet;
@@ -175,7 +174,7 @@ mod tests {
 
         let metrics_call =
             metrics::serve::<RegistryWrapper>(actix_web::web::Data::new(RegistryWrapper(registry)));
-        let resp = rt.block_on(metrics_call)?;
+        let resp = rt.block_on(metrics_call);
 
         assert_eq!(resp.status(), 200);
         if let actix_web::body::ResponseBody::Body(body) = resp.body() {
diff --git a/graph-builder/src/status.rs b/graph-builder/src/status.rs
index feb6f0d50..d6e748e3f 100644
--- a/graph-builder/src/status.rs
+++ b/graph-builder/src/status.rs
@@ -2,21 +2,18 @@
 
 use crate::graph::State;
 use actix_web::HttpResponse;
-use failure::Fallible;
 
 /// Expose liveness status.
 ///
 /// Status:
 ///  * Live (200 code): The upstream scrape loop thread is running
 ///  * Not Live (503 code): everything else.
-pub async fn serve_liveness(app_data: actix_web::web::Data<State>) -> Fallible<HttpResponse> {
-    let resp = if app_data.is_live() {
+pub async fn serve_liveness(app_data: actix_web::web::Data<State>) -> HttpResponse {
+    if app_data.is_live() {
         HttpResponse::Ok().finish()
     } else {
         HttpResponse::ServiceUnavailable().finish()
-    };
-
-    Ok(resp)
+    }
 }
 
 /// Expose readiness status.
@@ -24,12 +21,10 @@ pub async fn serve_liveness(app_data: actix_web::web::Data<State>) -> Fallible<H
 /// Status:
 ///  * Ready (200 code): a JSON graph as the result of a successful scrape is available.
 ///  * Not Ready (503 code): no JSON graph available yet.
-pub async fn serve_readiness(app_data: actix_web::web::Data<State>) -> Fallible<HttpResponse> {
-    let resp = if app_data.is_ready() {
+pub async fn serve_readiness(app_data: actix_web::web::Data<State>) -> HttpResponse {
+    if app_data.is_ready() {
         HttpResponse::Ok().finish()
     } else {
         HttpResponse::ServiceUnavailable().finish()
-    };
-
-    Ok(resp)
+    }
 }
diff --git a/policy-engine/Cargo.toml b/policy-engine/Cargo.toml
index b0536d5c3..e64f90578 100644
--- a/policy-engine/Cargo.toml
+++ b/policy-engine/Cargo.toml
@@ -11,7 +11,6 @@ actix-web = "^2.0"
 cincinnati = { path = "../cincinnati" }
 commons = { path = "../commons" }
 env_logger = "^0.6.0"
-failure = "^0.1.1"
 futures = "^0.3"
 hyper = "^0.13"
 lazy_static = "^1.2.0"
diff --git a/policy-engine/src/config/cli.rs b/policy-engine/src/config/cli.rs
index 6e0aece2a..cb7584fca 100644
--- a/policy-engine/src/config/cli.rs
+++ b/policy-engine/src/config/cli.rs
@@ -2,8 +2,8 @@
 
 use super::options;
 use super::AppSettings;
+use commons::prelude_errors::*;
 use commons::MergeOptions;
-use failure::Fallible;
 
 /// CLI configuration flags, top-level.
 #[derive(Debug, StructOpt)]
diff --git a/policy-engine/src/config/file.rs b/policy-engine/src/config/file.rs
index 7711d619d..ca453c441 100644
--- a/policy-engine/src/config/file.rs
+++ b/policy-engine/src/config/file.rs
@@ -3,8 +3,8 @@
 use super::options;
 use super::AppSettings;
 use commons::de::de_loglevel;
+use commons::prelude_errors::*;
 use commons::MergeOptions;
-use failure::{Fallible, ResultExt};
 use std::io::Read;
 use std::{fs, io, path};
 
@@ -53,7 +53,7 @@ impl FileOptions {
 }
 
 impl MergeOptions<Option<FileOptions>> for AppSettings {
-    fn try_merge(&mut self, opts: Option<FileOptions>) -> failure::Fallible<()> {
+    fn try_merge(&mut self, opts: Option<FileOptions>) -> Fallible<()> {
         if let Some(file) = opts {
             assign_if_some!(self.verbosity, file.verbosity);
             self.try_merge(file.policy)?;
diff --git a/policy-engine/src/config/options.rs b/policy-engine/src/config/options.rs
index 5404ed8fb..ca18f50d2 100644
--- a/policy-engine/src/config/options.rs
+++ b/policy-engine/src/config/options.rs
@@ -1,8 +1,8 @@
 //! Options shared by CLI and TOML.
 
 use super::AppSettings;
+use commons::prelude_errors::*;
 use commons::{de_path_prefix, parse_params_set, parse_path_prefix, MergeOptions};
-use failure::Fallible;
 use std::collections::HashSet;
 use std::net::IpAddr;
 
@@ -85,7 +85,7 @@ impl MergeOptions<Option<UpCincinnatiOptions>> for AppSettings {
 }
 
 /// Parse a URI from a string.
-pub fn uri_from_str<S>(input: S) -> failure::Fallible<hyper::Uri>
+pub fn uri_from_str<S>(input: S) -> Fallible<hyper::Uri>
 where
     S: AsRef<str>,
 {
diff --git a/policy-engine/src/config/settings.rs b/policy-engine/src/config/settings.rs
index ba6f49d9a..7dfc38328 100644
--- a/policy-engine/src/config/settings.rs
+++ b/policy-engine/src/config/settings.rs
@@ -3,7 +3,7 @@
 use super::{cli, file};
 use cincinnati::plugins::catalog::{self, PluginSettings};
 use cincinnati::plugins::BoxedPlugin;
-use failure::Fallible;
+use commons::prelude_errors::*;
 use hyper::Uri;
 use std::collections::HashSet;
 use std::net::{IpAddr, Ipv4Addr};
diff --git a/policy-engine/src/graph.rs b/policy-engine/src/graph.rs
index 869e8dfe4..90bbb2f1f 100644
--- a/policy-engine/src/graph.rs
+++ b/policy-engine/src/graph.rs
@@ -5,8 +5,7 @@ use actix_web::web::Query;
 use actix_web::{HttpRequest, HttpResponse};
 use cincinnati::plugins::BoxedPlugin;
 use cincinnati::CONTENT_TYPE;
-use commons::{self, GraphError};
-use failure::Fallible;
+use commons::{self, Fallible, GraphError};
 use prometheus::{histogram_opts, Counter, Histogram, Registry};
 use serde_json;
 use std::collections::HashMap;
@@ -109,7 +108,6 @@ pub(crate) mod tests {
     use actix_web::http;
     use cincinnati::plugins::prelude::*;
     use mockito;
-    use std::error::Error;
     use tokio::runtime::Runtime;
 
     pub(crate) fn common_init() -> Runtime {
@@ -156,7 +154,7 @@ pub(crate) mod tests {
     }
 
     #[test]
-    fn failed_plugin_execution() -> Result<(), Box<dyn Error>> {
+    fn failed_plugin_execution() -> Result<(), Error> {
         let mut rt = common_init();
 
         let plugins = cincinnati::plugins::catalog::build_plugins(
@@ -199,12 +197,12 @@ pub(crate) mod tests {
             {
                 Ok(())
             }
-            res => Err(format!("expected InvalidParams error, got: {:?}", res).into()),
+            res => bail!("expected InvalidParams error, got: {:?}", res),
         }
     }
 
     #[test]
-    fn webservice_graph_json_response() -> Result<(), Box<dyn Error>> {
+    fn webservice_graph_json_response() -> Result<(), Error> {
         let _ = common_init();
 
         enum TestResult {
@@ -236,7 +234,7 @@ pub(crate) mod tests {
             passed_params: &[(&str, &str)],
             plugin_config: &[Box<dyn PluginSettings>],
             expected_result: &TestResult,
-        ) -> Result<(), Box<dyn Error>> {
+        ) -> Result<(), Error> {
             let mut runtime = Runtime::new().unwrap();
             let service_uri_base = "/graph";
             let service_uri = format!(
@@ -274,34 +272,31 @@ pub(crate) mod tests {
                         .route(actix_web::web::get().to(graph::index)),
                 );
 
-            let body_future: Box<
-                dyn core::future::Future<Output = Result<_, Box<dyn Error>>> + Unpin,
-            > = Box::new(Box::pin(async {
-                let mut pe_svc = actix_web::test::init_service(app).await;
-                let mut response = actix_web::test::call_service(
-                    &mut pe_svc,
-                    actix_web::test::TestRequest::with_uri(&service_uri)
-                        .header("Accept", "application/json")
-                        .to_request(),
-                )
-                .await;
-
-                if response.status() != expected_result.status_code() {
-                    return Err(format!("unexpected statuscode:{}", response.status()).into());
-                };
-
-                match response.take_body() {
-                    actix_web::dev::ResponseBody::Body(b) => match b {
-                        actix_web::dev::Body::Bytes(bytes) => {
-                            Ok(std::str::from_utf8(&bytes)?.to_owned())
-                        }
-                        unknown => {
-                            return Err(format!("expected byte body, got '{:?}'", unknown).into())
-                        }
-                    },
-                    _ => return Err("expected body response".into()),
-                }
-            }));
+            let body_future: Box<dyn core::future::Future<Output = Result<_, Error>> + Unpin> =
+                Box::new(Box::pin(async {
+                    let mut pe_svc = actix_web::test::init_service(app).await;
+                    let mut response = actix_web::test::call_service(
+                        &mut pe_svc,
+                        actix_web::test::TestRequest::with_uri(&service_uri)
+                            .header("Accept", "application/json")
+                            .to_request(),
+                    )
+                    .await;
+
+                    if response.status() != expected_result.status_code() {
+                        bail!("unexpected statuscode:{}", response.status());
+                    };
+
+                    match response.take_body() {
+                        actix_web::dev::ResponseBody::Body(b) => match b {
+                            actix_web::dev::Body::Bytes(bytes) => {
+                                Ok(std::str::from_utf8(&bytes)?.to_owned())
+                            }
+                            unknown => bail!("expected byte body, got '{:?}'", unknown),
+                        },
+                        _ => bail!("expected body response"),
+                    }
+                }));
 
             let body = runtime.block_on(body_future)?;
 
@@ -310,7 +305,7 @@ pub(crate) mod tests {
             let toplevel = if let Some(obj) = json.as_object_mut() {
                 obj
             } else {
-                return Err("not a JSON object".into());
+                bail!("not a JSON object");
             };
 
             match expected_result {
@@ -321,24 +316,23 @@ pub(crate) mod tests {
                     if let Some(kind) = toplevel.remove("kind") {
                         assert_eq!(kind, expected_error.kind())
                     } else {
-                        return Err("expected 'kind' in JSON object".into());
+                        bail!("expected 'kind' in JSON object");
                     }
 
                     if let Some(value) = toplevel.remove("value") {
                         if let Some(result_value) = value.as_str() {
                             if !result_value.contains(&expected_error.value()) {
-                                return Err(format!(
+                                bail!(
                                     "value '{}' doesn't contain: \'{}\'",
                                     result_value,
                                     expected_error.value(),
                                 )
-                                .into());
                             }
                         } else {
-                            return Err(format!("couldn't parse '{}' as string", value).into());
+                            bail!("couldn't parse '{}' as string", value);
                         }
                     } else {
-                        return Err("expected 'value' in JSON object".into());
+                        bail!("expected 'value' in JSON object");
                     }
                 }
             };
@@ -407,7 +401,7 @@ pub(crate) mod tests {
                 &test_param.plugin_config,
                 &test_param.expected_result,
             )
-            .map_err(|e| format!("test '{}' failed: {}", test_param.name, e).into())
+            .map_err(|e| format_err!("test '{}' failed: {}", test_param.name, e))
         })
     }
 }
diff --git a/policy-engine/src/main.rs b/policy-engine/src/main.rs
index 072ca78a2..9d91bacbe 100644
--- a/policy-engine/src/main.rs
+++ b/policy-engine/src/main.rs
@@ -7,8 +7,6 @@ extern crate cincinnati;
 #[macro_use]
 extern crate commons;
 #[macro_use]
-extern crate failure;
-#[macro_use]
 extern crate lazy_static;
 #[macro_use]
 extern crate log;
@@ -28,7 +26,7 @@ mod openapi;
 use actix_web::{middleware, App, HttpServer};
 use cincinnati::plugins::BoxedPlugin;
 use commons::metrics::{self, RegistryWrapper};
-use failure::Error;
+use commons::prelude_errors::*;
 use prometheus::{labels, opts, Counter, Registry};
 use std::collections::HashSet;
 
diff --git a/policy-engine/src/openapi.rs b/policy-engine/src/openapi.rs
index 797f3c22c..1085b9291 100644
--- a/policy-engine/src/openapi.rs
+++ b/policy-engine/src/openapi.rs
@@ -1,5 +1,6 @@
 use crate::AppState;
 use actix_web::HttpResponse;
+use commons::prelude_errors::*;
 use openapiv3::{OpenAPI, ReferenceOr};
 use std::collections::HashSet;
 
@@ -9,14 +10,14 @@ const SPEC: &str = include_str!("openapiv3.json");
 pub(crate) fn index(app_data: actix_web::web::Data<AppState>) -> HttpResponse {
     let path_prefix = &app_data.path_prefix;
 
-    let mut spec_object: OpenAPI = match serde_json::from_str(SPEC) {
-        Ok(o) => o,
-        Err(e) => {
-            let e = format_err!("Could not deserialize to OpenAPI object: {}", e);
-            error!("{}", e);
-            return HttpResponse::from_error(e.into());
-        }
-    };
+    let mut spec_object: OpenAPI =
+        match serde_json::from_str(SPEC).context("Could not deserialize to OpenAPI object") {
+            Ok(o) => o,
+            Err(e) => {
+                error!("{}", e);
+                return actix_web::error::ErrorInternalServerError(e).into();
+            }
+        };
 
     // Add mandatory parameters to the `graph` endpoint.
     if let Some(path) = spec_object.paths.get_mut("/v1/graph") {
@@ -26,14 +27,13 @@ pub(crate) fn index(app_data: actix_web::web::Data<AppState>) -> HttpResponse {
     // Prefix all paths with `path_prefix`
     spec_object.paths = rewrite_paths(spec_object.paths, path_prefix);
 
-    match serde_json::to_string(&spec_object) {
-        Ok(s) => HttpResponse::from(s),
-        Err(e) => {
-            let e = format_err!("Could not serialize OpenAPI object: {}", e);
-            error!("{}", e);
-            HttpResponse::from_error(e.into())
-        }
-    }
+    serde_json::to_string(&spec_object)
+        .context("Could not serialize OpenAPI object")
+        .map(HttpResponse::from)
+        .unwrap_or_else(|e| {
+            error!("{:?}", e);
+            actix_web::error::ErrorInternalServerError(e).into()
+        })
 }
 
 fn rewrite_paths(paths: openapiv3::Paths, path_prefix: &str) -> openapiv3::Paths {
diff --git a/prometheus-query/Cargo.toml b/prometheus-query/Cargo.toml
index d8623187a..c73be9546 100644
--- a/prometheus-query/Cargo.toml
+++ b/prometheus-query/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2018"
 
 [dependencies]
 commons = { path = "../commons" }
-failure = "^0.1.5"
+anyhow = "^1.0"
 futures = "^0.3"
 reqwest = "^0.9.8"
 serde = { version = "^1.0.84", features = ["derive"] }
diff --git a/prometheus-query/src/lib.rs b/prometheus-query/src/lib.rs
index bbd6f92c8..e48dac3d8 100644
--- a/prometheus-query/src/lib.rs
+++ b/prometheus-query/src/lib.rs
@@ -2,8 +2,6 @@
 //!
 //! See https://github.com/prometheus/prometheus/blob/9de0ab3c8a32f8e09ab68f793dab0c76ec3e93d0/docs/querying/api.md#http-api
 
-#[macro_use]
-extern crate failure;
 extern crate futures;
 extern crate reqwest;
 extern crate serde;
diff --git a/prometheus-query/src/v1/mod.rs b/prometheus-query/src/v1/mod.rs
index deabe2a43..b1dfea03f 100644
--- a/prometheus-query/src/v1/mod.rs
+++ b/prometheus-query/src/v1/mod.rs
@@ -1,6 +1,6 @@
 //! Asynchronous Prometheus HTTP API Client /v1 implementation
 
-use failure::Fallible;
+use anyhow::{bail, Result as Fallible};
 use reqwest;
 
 pub mod queries;
diff --git a/prometheus-query/src/v1/queries/instant.rs b/prometheus-query/src/v1/queries/instant.rs
index c2817b135..e712088b4 100644
--- a/prometheus-query/src/v1/queries/instant.rs
+++ b/prometheus-query/src/v1/queries/instant.rs
@@ -1,7 +1,7 @@
 //! Impelement instant queries
 
 use super::*;
-use failure::Fallible;
+use anyhow::Result as Fallible;
 use reqwest;
 use std::time::Duration;
 
diff --git a/prometheus-query/src/v1/queries/mod.rs b/prometheus-query/src/v1/queries/mod.rs
index b9017ce63..895b651ea 100644
--- a/prometheus-query/src/v1/queries/mod.rs
+++ b/prometheus-query/src/v1/queries/mod.rs
@@ -63,7 +63,7 @@ impl VectorResult {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use failure::Fallible;
+    use anyhow::{bail, Result as Fallible};
 
     #[test]
     fn deserialize_queryresult() -> Fallible<()> {
diff --git a/quay/Cargo.toml b/quay/Cargo.toml
index 340cb96db..a1b094e71 100644
--- a/quay/Cargo.toml
+++ b/quay/Cargo.toml
@@ -6,7 +6,7 @@ publish = false
 edition = "2018"
 
 [dependencies]
-failure = "^0.1.5"
+anyhow = "1.0"
 futures = "^0.3"
 reqwest = { version = "^0.10", features = ["json"] }
 serde = "^1.0.84"
@@ -20,4 +20,4 @@ tokio = "^0.2"
 
 [features]
 test-net = []
-test-net-private = []
\ No newline at end of file
+test-net-private = []
diff --git a/quay/src/lib.rs b/quay/src/lib.rs
index 7e99e39b5..e884623a2 100644
--- a/quay/src/lib.rs
+++ b/quay/src/lib.rs
@@ -1,12 +1,9 @@
 //! Asynchronous client for quay.io v1 API.
 
-#[macro_use]
-extern crate failure;
 #[macro_use]
 extern crate serde_derive;
 
-use failure::Fallible;
-use failure::ResultExt;
+use anyhow::{bail, format_err, Context, Result as Fallible};
 use std::fs::File;
 use std::io::{BufRead, BufReader};
 use std::path::Path;
diff --git a/quay/src/v1/manifest.rs b/quay/src/v1/manifest.rs
index 870583e2c..51bf4efc1 100644
--- a/quay/src/v1/manifest.rs
+++ b/quay/src/v1/manifest.rs
@@ -1,7 +1,7 @@
 //! Manifest API.
 
 use super::Client;
-use failure::Error;
+use anyhow::Error;
 use reqwest::Method;
 
 /// API result with all labels.
diff --git a/quay/src/v1/mod.rs b/quay/src/v1/mod.rs
index 4b4f98c95..de9f17a5a 100644
--- a/quay/src/v1/mod.rs
+++ b/quay/src/v1/mod.rs
@@ -1,4 +1,4 @@
-use failure::Fallible;
+use anyhow::Result as Fallible;
 use reqwest;
 
 mod manifest;
diff --git a/quay/src/v1/tag.rs b/quay/src/v1/tag.rs
index caa24d7f5..5249673b6 100644
--- a/quay/src/v1/tag.rs
+++ b/quay/src/v1/tag.rs
@@ -1,8 +1,8 @@
 //! Tag API.
 
 use super::Client;
+use anyhow::Result as Fallible;
 use async_stream::stream;
-use failure::Fallible;
 use futures::Stream;
 use reqwest::Method;
 
diff --git a/quay/tests/net/private.rs b/quay/tests/net/private.rs
index a8f63ee33..6192f4acd 100644
--- a/quay/tests/net/private.rs
+++ b/quay/tests/net/private.rs
@@ -1,3 +1,4 @@
+use anyhow::Error;
 use futures::StreamExt;
 use tokio::runtime::Runtime;
 
@@ -24,7 +25,7 @@ fn test_wrong_auth() {
             .stream_tags(repo, true)
             .await
             .map(Result::unwrap_err)
-            .collect::<Vec<failure::Error>>()
+            .collect::<Vec<Error>>()
             .await
     };
     rt.block_on(fetch_tags);
