From 252702049e55cc2903a07fd24e6a165a33c54026 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 25 Jun 2026 14:17:00 +0200 Subject: [PATCH] vmm: migration: print whole error chain on error In [0] we agreed on the current format. When ch-remote or cloud-hypervisor exit with an error, they nicely print the whole chain. This, however, doesn't work when simply doing `error!("error: {e}")` - which is what we currently do for migration-related errors. This commit walks the chain of errors and prints all components in a single line. This massively improves the quality of error messages and helps tracing down where an error is originating from. Using ` => ` as separator is better than `\n` which doesn't work well in our current log format. # Example (Before - Bad) ``` cloud-hypervisor: 2.859287s: ERROR:vmm/src/lib.rs:2021 -- Migration failed: Failed to send migratable component snapshot ``` # Example (New - Better) ``` cloud-hypervisor: 2.296160s: ERROR:vmm/src/lib.rs:2038 -- Migration failed: Failed to send migratable component snapshot => Error connecting to TCP socket => Connection refused (os error 111) ``` [0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7066 On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster --- vmm/src/lib.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 844621952..ef4ec5793 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -4,6 +4,7 @@ // use std::collections::HashMap; +use std::error::Error as StdError; use std::fs::File; use std::io::{Read, Write, stdout}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; @@ -15,7 +16,7 @@ use std::sync::mpsc; use std::sync::mpsc::{Receiver, RecvError, SendError, Sender, channel}; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; -use std::{any, io, mem, panic, path, process, result, thread}; +use std::{any, io, iter, mem, panic, path, process, result, thread}; use anyhow::{Context, anyhow}; #[cfg(feature = "dbus_api")] @@ -2018,7 +2019,22 @@ impl Vmm { } } Err(e) => { - error!("Migration failed: {e}"); + // Mimic the error chain that CH prints on error in the log. + // Required to get useful error messages in the log. + let top_error: &dyn StdError = &e; + let error_chain_str = { + iter::successors(Some(top_error), |sub_error| { + // Dereference necessary to mitigate rustc compiler bug. + // See + (*sub_error).source() + }) + // Important to use the plain Display impl to not interfere + // with anyhow's "smart" printing + .map(|e| format!("{e}")) + .collect::>() + .join(" => ") + }; + error!("Migration failed: {error_chain_str}"); try_resume_vm_after_failed_migration(vm); } }