From bd82539516e0d5fc58485b360a327d799163888b Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 30 Mar 2026 16:00:23 -0400 Subject: [PATCH] Preserve metadata deserialize error details --- lib/crates/fabro-checkpoint/src/branch.rs | 4 +-- lib/crates/fabro-checkpoint/src/error.rs | 2 +- lib/crates/fabro-workflow/src/error.rs | 33 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/crates/fabro-checkpoint/src/branch.rs b/lib/crates/fabro-checkpoint/src/branch.rs index bf849ea45..f5adc10a8 100644 --- a/lib/crates/fabro-checkpoint/src/branch.rs +++ b/lib/crates/fabro-checkpoint/src/branch.rs @@ -47,7 +47,7 @@ impl<'a> BranchStore<'a> { self.objects .write_commit(empty_tree, &[], "initialize branch", &self.author)?; self.objects.update_ref(&self.branch, commit_oid)?; - debug!(branch = %self.branch, "Created git storage branch"); + debug!(branch = %self.branch, "Created checkpoint branch"); Ok(()) } @@ -74,7 +74,7 @@ impl<'a> BranchStore<'a> { self.objects .write_commit(new_tree, &[parent_oid], message, &self.author)?; self.objects.update_ref(&self.branch, commit_oid)?; - debug!(branch = %self.branch, commit = %commit_oid, "Wrote git storage commit"); + debug!(branch = %self.branch, commit = %commit_oid, "Wrote checkpoint commit"); Ok(commit_oid) } diff --git a/lib/crates/fabro-checkpoint/src/error.rs b/lib/crates/fabro-checkpoint/src/error.rs index 8f186db80..fa5df4467 100644 --- a/lib/crates/fabro-checkpoint/src/error.rs +++ b/lib/crates/fabro-checkpoint/src/error.rs @@ -22,7 +22,7 @@ pub enum MetadataError { #[error(transparent)] Storage(#[from] Error), - #[error("deserialize {entity} on branch {branch}")] + #[error("deserialize {entity} on branch {branch}: {source}")] Deserialize { entity: &'static str, branch: String, diff --git a/lib/crates/fabro-workflow/src/error.rs b/lib/crates/fabro-workflow/src/error.rs index d9deeccd5..f4b51e2e8 100644 --- a/lib/crates/fabro-workflow/src/error.rs +++ b/lib/crates/fabro-workflow/src/error.rs @@ -362,6 +362,7 @@ pub type Result = std::result::Result; mod tests { use super::*; use crate::outcome::OutcomeExt; + use fabro_checkpoint::MetadataError; use fabro_llm::error::ProviderErrorDetail; #[test] @@ -432,6 +433,38 @@ mod tests { assert!(err.is_err()); } + #[test] + fn metadata_checkpoint_deserialize_error_preserves_source_detail() { + let source = serde_json::from_str::("not json").unwrap_err(); + let source_message = source.to_string(); + let fabro_error = FabroError::from(MetadataError::Deserialize { + entity: "checkpoint", + branch: "fabro/meta/run-1".to_string(), + source, + }); + + assert!(matches!(fabro_error, FabroError::Checkpoint(_))); + let message = fabro_error.to_string(); + assert!(message.contains("deserialize checkpoint on branch fabro/meta/run-1")); + assert!(message.contains(&source_message)); + } + + #[test] + fn metadata_non_checkpoint_deserialize_error_maps_to_engine_with_source_detail() { + let source = serde_json::from_str::("not json").unwrap_err(); + let source_message = source.to_string(); + let fabro_error = FabroError::from(MetadataError::Deserialize { + entity: "run record", + branch: "fabro/meta/run-1".to_string(), + source, + }); + + assert!(matches!(fabro_error, FabroError::Engine { .. })); + let message = fabro_error.to_string(); + assert!(message.contains("deserialize run record on branch fabro/meta/run-1")); + assert!(message.contains(&source_message)); + } + #[test] fn cancelled_error_display() { let err = FabroError::Cancelled;