From 2d80c2b37fd103f2e3851e4c0e14a8ec33a6fefa Mon Sep 17 00:00:00 2001 From: rabi Date: Thu, 19 Feb 2026 10:57:04 +0530 Subject: [PATCH 1/2] fix: skip whitespace-only text blocks in Anthropic Fixes 400 error from Anthropic API: "messages: text content blocks must contain non-whitespace text". This occurs when assistant messages have their trailing whitespace trimmed to empty strings but the empty text block remains alongside other content like tool requests. Change-Id: I65a1283f7dbb3599bdd869ead8b942db019f69df Signed-off-by: rabi --- crates/goose/src/providers/formats/anthropic.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index f47a387aa832..4b59ec40428d 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -44,10 +44,12 @@ pub fn format_messages(messages: &[Message]) -> Vec { for msg_content in &message.content { match msg_content { MessageContent::Text(text) => { - content.push(json!({ - TYPE_FIELD: TEXT_TYPE, - TEXT_TYPE: text.text - })); + if !text.text.trim().is_empty() { + content.push(json!({ + TYPE_FIELD: TEXT_TYPE, + TEXT_TYPE: text.text + })); + } } MessageContent::ToolRequest(tool_request) => { match &tool_request.tool_call { From a3e35843616d3f4e7ca14573d0542a70db3fcade Mon Sep 17 00:00:00 2001 From: rabi Date: Thu, 19 Feb 2026 10:57:44 +0530 Subject: [PATCH 2/2] test: add test for whitespace-only text block filtering Change-Id: I1b6a15a3ed0a0c5e2e5462c5bc7888a1535eb137 Signed-off-by: rabi --- .../goose/src/providers/formats/anthropic.rs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index 4b59ec40428d..9f7ab7898477 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -1007,4 +1007,37 @@ mod tests { ); assert_eq!(spec[1]["content"][0]["is_error"], true); } + + #[test] + fn test_whitespace_only_text_blocks_are_skipped() { + let messages = vec![ + Message::user().with_text("Hello"), + Message::assistant().with_text("").with_tool_request( + "tool_1", + Ok(CallToolRequestParams { + meta: None, + task: None, + name: "search".into(), + arguments: Some(object!({"query": "test"})), + }), + ), + Message::user().with_tool_response( + "tool_1", + Ok(rmcp::model::CallToolResult { + content: vec![], + structured_content: None, + is_error: Some(false), + meta: None, + }), + ), + ]; + + let spec = format_messages(&messages); + + assert_eq!(spec.len(), 3); + + let assistant_content = spec[1]["content"].as_array().unwrap(); + assert_eq!(assistant_content.len(), 1); + assert_eq!(assistant_content[0]["type"], "tool_use"); + } }