From d13d2069b98fec09e701421ce5a8196b3385efbb Mon Sep 17 00:00:00 2001 From: Anshul Garg Date: Fri, 13 Mar 2026 16:34:34 +0530 Subject: [PATCH 1/2] fix(sheets): report error for invalid --json-values instead of silent empty append parse_append_args() used unwrap_or_default() when JSON parsing failed, silently converting invalid input into an empty Vec. This caused +append --json-values with malformed JSON to append an empty row without any error message, making debugging very difficult. - Change parse_append_args() to return Result - Surface the serde_json error message with guidance on expected format - Add #[derive(Debug)] to AppendConfig for Result unwrap in tests - Add tests for valid JSON and invalid JSON error paths --- src/helpers/sheets.rs | 53 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/helpers/sheets.rs b/src/helpers/sheets.rs index 9e347b4d..f9d1d92a 100644 --- a/src/helpers/sheets.rs +++ b/src/helpers/sheets.rs @@ -102,7 +102,7 @@ TIPS: ) -> Pin> + Send + 'a>> { Box::pin(async move { if let Some(matches) = matches.subcommand_matches("+append") { - let config = parse_append_args(matches); + let config = parse_append_args(matches)?; let (params_str, body_str, scopes) = build_append_request(&config, doc)?; let scope_strs: Vec<&str> = scopes.iter().map(|s| s.as_str()).collect(); @@ -257,6 +257,7 @@ fn build_read_request( /// Configuration for appending values to a spreadsheet. /// /// Holds the parsed arguments for the `+append` subcommand. +#[derive(Debug)] pub struct AppendConfig { /// The ID of the spreadsheet to append to. pub spreadsheet_id: String, @@ -267,7 +268,8 @@ pub struct AppendConfig { /// Parses arguments for the `+append` command. /// /// Supports both `--values` (single row) and `--json-values` (single or multi-row). -pub fn parse_append_args(matches: &ArgMatches) -> AppendConfig { +/// Returns a validation error if `--json-values` contains invalid JSON. +pub fn parse_append_args(matches: &ArgMatches) -> Result { let values = if let Some(json_str) = matches.get_one::("json-values") { // Try parsing as array-of-arrays (multi-row) first if let Ok(parsed) = serde_json::from_str::>>(json_str) { @@ -276,10 +278,9 @@ pub fn parse_append_args(matches: &ArgMatches) -> AppendConfig { // Single flat array — treat as one row vec![parsed] } else { - eprintln!( - "Warning: --json-values is not valid JSON; expected an array or array-of-arrays" - ); - Vec::new() + return Err(GwsError::Validation(format!( + "--json-values is not valid JSON: expected an array like '[\"a\",\"b\"]' or array-of-arrays like '[[\"a\",\"b\"],[\"c\",\"d\"]]'." + ))); } } else if let Some(values_str) = matches.get_one::("values") { vec![values_str.split(',').map(|s| s.to_string()).collect()] @@ -287,10 +288,10 @@ pub fn parse_append_args(matches: &ArgMatches) -> AppendConfig { Vec::new() }; - AppendConfig { + Ok(AppendConfig { spreadsheet_id: matches.get_one::("spreadsheet").unwrap().clone(), values, - } + }) } /// Configuration for reading values from a spreadsheet. @@ -395,7 +396,7 @@ mod tests { #[test] fn test_parse_append_args_values() { let matches = make_matches_append(&["test", "--spreadsheet", "123", "--values", "a,b,c"]); - let config = parse_append_args(&matches); + let config = parse_append_args(&matches).unwrap(); assert_eq!(config.spreadsheet_id, "123"); assert_eq!(config.values, vec![vec!["a", "b", "c"]]); } @@ -409,7 +410,7 @@ mod tests { "--json-values", r#"["a","b","c"]"#, ]); - let config = parse_append_args(&matches); + let config = parse_append_args(&matches).unwrap(); assert_eq!(config.values, vec![vec!["a", "b", "c"]]); } @@ -422,7 +423,7 @@ mod tests { "--json-values", r#"[["Alice","100"],["Bob","200"]]"#, ]); - let config = parse_append_args(&matches); + let config = parse_append_args(&matches).unwrap(); assert_eq!( config.values, vec![vec!["Alice", "100"], vec!["Bob", "200"]] @@ -447,6 +448,36 @@ mod tests { assert_eq!(values[1], json!(["Bob", "200"])); } + #[test] + fn test_parse_append_args_json_valid() { + let matches = make_matches_append(&[ + "test", + "--spreadsheet", + "123", + "--json-values", + r#"["a","b","c"]"#, + ]); + let config = parse_append_args(&matches).unwrap(); + assert_eq!(config.values, vec![vec!["a", "b", "c"]]); + } + + #[test] + fn test_parse_append_args_json_invalid_returns_error() { + let matches = make_matches_append(&[ + "test", + "--spreadsheet", + "123", + "--json-values", + "not valid json", + ]); + let err = parse_append_args(&matches).unwrap_err(); + let msg = err.to_string(); + assert!( + msg.contains("--json-values is not valid JSON"), + "expected JSON error message, got: {msg}" + ); + } + #[test] fn test_parse_read_args() { let matches = make_matches_read(&["test", "--spreadsheet", "123", "--range", "A1:B2"]); From d3d3a513cb2500897dff0483c2c31fd843745f6f Mon Sep 17 00:00:00 2001 From: Anshul Garg Date: Sat, 14 Mar 2026 02:01:30 +0530 Subject: [PATCH 2/2] chore: add changeset --- .changeset/fix-sheets-json-error.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fix-sheets-json-error.md diff --git a/.changeset/fix-sheets-json-error.md b/.changeset/fix-sheets-json-error.md new file mode 100644 index 00000000..8e99f8a2 --- /dev/null +++ b/.changeset/fix-sheets-json-error.md @@ -0,0 +1,5 @@ +--- +"@googleworkspace/cli": patch +--- + +Report validation error for invalid --json-values instead of silent empty append