1 // Copyright © 2025 Cyberus Technology GmbH 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 use std::error::Error; 6 7 /// Prints a chain of errors to the user in a consistent manner. 8 /// The user will see a clear chain of errors, followed by debug output 9 /// for opening issues. 10 pub fn cli_print_error_chain<'a>( 11 top_error: &'a (dyn Error + 'static), 12 component: &str, 13 // Function optionally returning the display representation of an error. 14 display_modifier: impl Fn( 15 /* level */ usize, 16 /*indention */ usize, 17 &'a (dyn Error + 'static), 18 ) -> Option<String>, 19 ) { 20 eprint!("Error: {component} exited with the following "); 21 if top_error.source().is_none() { 22 eprintln!("error:"); 23 eprintln!(" {top_error}"); 24 } else { 25 eprintln!("chain of errors:"); 26 std::iter::successors(Some(top_error), |sub_error| { 27 // Dereference necessary to mitigate rustc compiler bug. 28 // See <https://github.com/rust-lang/rust/issues/141673> 29 (*sub_error).source() 30 }) 31 .enumerate() 32 .for_each(|(level, error)| { 33 // Special case: handling of HTTP Server responses in ch-remote 34 if let Some(message) = display_modifier(level, 2, error) { 35 eprintln!("{message}"); 36 } else { 37 eprintln!(" {level}: {error}"); 38 } 39 }); 40 } 41 42 eprintln!(); 43 eprintln!("Debug Info: {top_error:?}"); 44 } 45