fix(robot): replace JSON serialization unwrap with graceful error handling

Replace serde_json::to_string(&output).unwrap() with match-based error
handling across all robot-mode JSON printers. On serialization failure,
the error is now written to stderr instead of panicking. This hardens
the CLI against unexpected Serialize failures in production.

Affected commands: count (2), embed, generate-docs, ingest (2), search,
stats, sync (2), sync-status, timeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
teernisse
2026-02-18 13:28:47 -05:00
parent 8442bcf367
commit 097249f4e6
9 changed files with 48 additions and 12 deletions

View File

@@ -257,7 +257,10 @@ pub fn print_event_count_json(counts: &EventCounts, elapsed_ms: u64) {
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
pub fn print_event_count(counts: &EventCounts) {
@@ -325,7 +328,10 @@ pub fn print_count_json(result: &CountResult, elapsed_ms: u64) {
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
pub fn print_count(result: &CountResult) {

View File

@@ -137,5 +137,8 @@ pub fn print_embed_json(result: &EmbedCommandResult, elapsed_ms: u64) {
data: result,
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}

View File

@@ -259,7 +259,10 @@ pub fn print_generate_docs_json(result: &GenerateDocsResult, elapsed_ms: u64) {
},
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
#[cfg(test)]

View File

@@ -982,7 +982,10 @@ pub fn print_ingest_summary_json(result: &IngestResult, elapsed_ms: u64) {
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
pub fn print_ingest_summary(result: &IngestResult) {
@@ -1109,5 +1112,8 @@ pub fn print_dry_run_preview_json(preview: &DryRunPreview) {
data: preview.clone(),
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}

View File

@@ -439,5 +439,8 @@ pub fn print_search_results_json(
let expanded = crate::cli::robot::expand_fields_preset(f, "search");
crate::cli::robot::filter_fields(&mut value, "results", &expanded);
}
println!("{}", serde_json::to_string(&value).unwrap());
match serde_json::to_string(&value) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}

View File

@@ -585,5 +585,8 @@ pub fn print_stats_json(result: &StatsResult, elapsed_ms: u64) {
},
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}

View File

@@ -746,7 +746,10 @@ pub fn print_sync_json(result: &SyncResult, elapsed_ms: u64, metrics: Option<&Me
stages,
},
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
#[derive(Debug, Default, Serialize)]
@@ -880,7 +883,10 @@ pub fn print_sync_dry_run_json(result: &SyncDryRunResult) {
},
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
#[cfg(test)]

View File

@@ -268,7 +268,10 @@ pub fn print_sync_status_json(result: &SyncStatusResult, elapsed_ms: u64) {
meta: RobotMeta { elapsed_ms },
};
println!("{}", serde_json::to_string(&output).unwrap());
match serde_json::to_string(&output) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
pub fn print_sync_status(result: &SyncStatusResult) {

View File

@@ -374,7 +374,10 @@ pub fn print_timeline_json_with_meta(
let expanded = crate::cli::robot::expand_fields_preset(f, "timeline");
crate::cli::robot::filter_fields(&mut value, "events", &expanded);
}
println!("{}", serde_json::to_string(&value).unwrap());
match serde_json::to_string(&value) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("Error serializing to JSON: {e}"),
}
}
#[derive(Serialize)]