diff --git a/src/bin/vibebox.rs b/src/bin/vibebox.rs index 51bdadf..000f817 100644 --- a/src/bin/vibebox.rs +++ b/src/bin/vibebox.rs @@ -120,9 +120,15 @@ fn main() -> Result<()> { tracing::debug!(auto_shutdown_ms, "auto shutdown config"); let manager_conn = vm_manager::ensure_manager(&raw_args, auto_shutdown_ms, config_override.as_deref()) - .map_err(|err| color_eyre::eyre::eyre!(err.to_string()))?; + .map_err(|err| { + tracing::error!(error = %err, "failed to ensure vm manager"); + color_eyre::eyre::eyre!(err.to_string()) + })?; - instance::run_with_ssh(manager_conn).map_err(|err| color_eyre::eyre::eyre!(err.to_string()))?; + instance::run_with_ssh(manager_conn).map_err(|err| { + tracing::error!(error = %err, "failed to ensure vm manager"); + color_eyre::eyre::eyre!(err.to_string()) + })?; tracing::info!("See you again — keep vibecoding (no SEVs, only vibes) 😈"); diff --git a/src/instance.rs b/src/instance.rs index e160c3a..f7b77e6 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -266,6 +266,11 @@ fn wait_for_vm_ipv4( Ok(status) => { status_missing = false; let status = status.trim().to_string(); + if status.starts_with("error:") { + let _ = fs::remove_file(&status_path); + let message = status.trim_start_matches("error:").trim().to_string(); + return Err(message.into()); + } if !status.is_empty() && last_status.as_deref() != Some(status.as_str()) { tracing::info!("[background]: {}", status); last_status = Some(status); diff --git a/src/vm_manager.rs b/src/vm_manager.rs index 540b922..ae65bdf 100644 --- a/src/vm_manager.rs +++ b/src/vm_manager.rs @@ -17,6 +17,7 @@ use std::{ use crate::{ config::CONFIG_PATH_ENV, + instance::STATUS_FILE_NAME, instance::VM_ROOT_LOG_NAME, instance::{ DEFAULT_SSH_USER, InstanceConfig, build_ssh_login_actions, ensure_instance_dir, @@ -765,6 +766,10 @@ fn run_manager_with( ); tracing::info!("vm manager vm run completed"); let vm_err = vm_result.err().map(|e| e.to_string()); + if let Some(err) = &vm_err { + let status_path = instance_dir.join(STATUS_FILE_NAME); + let _ = fs::write(&status_path, format!("error: {err}")); + } let _ = event_tx.send(ManagerEvent::VmExited(vm_err.clone())); let event_loop_result: Result<(), String> = event_loop_handle .join()