Skip to content

Conversation

@zanesq
Copy link
Collaborator

@zanesq zanesq commented Jan 7, 2026

Follow up for #6094

Summary: Session Loading Backward Compatibility Fix

Problem

Users reported an error when loading/chatting after upgrading the desktop app: stream error: failed to read session: data did not match any variant of untagged enum ResultFormat at line 1 column 136

Root Cause

The issue was a schema mismatch between old and new session data formats:

  • Old format (ToolCall): arguments: serde_json::Value (could be any JSON type)
  • New format (CallToolRequestParam): arguments: Option<JsonObject> (must be an object or null)

When deserializing old sessions where arguments was a string, array, or number, the new deserialization logic failed because it couldn't match any variant of the ResultFormat enum.

Solution

Modified crates/goose/src/conversation/tool_result_serde.rs to handle legacy ToolCall format:

  1. Added a LegacyToolCall struct to accept arguments: serde_json::Value
  2. Updated the deserialize function to include a LegacySuccess variant for backward compatibility
  3. Added conversion logic in LegacyToolCall::into_call_tool_request_param():
    • JSON object → used directly as Some(map)
    • null → converted to None
    • Other types (string, number, array, boolean) → wrapped in {"value": <original>}

Files Changed

crates/goose/src/conversation/tool_result_serde.rs

  • Added LegacyToolCall struct with arguments: serde_json::Value
  • Added into_call_tool_request_param() conversion method
  • Modified deserialize function to handle both new and legacy formats

crates/goose/src/conversation/message.rs

  • Added 5 new unit tests covering legacy argument types:
    • test_legacy_tool_request_with_value_arguments (string)
    • test_legacy_tool_request_with_array_arguments
    • test_legacy_tool_request_with_number_arguments
    • test_legacy_tool_request_with_null_arguments
    • test_legacy_tool_request_with_object_arguments

Verification

  • ✅ Code compiles successfully
  • ✅ All 27 message tests pass
  • ✅ Clippy checks pass
  • ✅ Code formatted with cargo fmt

@zanesq zanesq requested a review from DOsinga January 7, 2026 22:44
}
}

#[test]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests are rather repetitive - if you wanted to do this, turn them into parameterized tests that only have the difference between the cases rather than repeating yourself.

but we should maybe think one deeper on how we avoid breaking this in the future - it happened before when we change the message format. adding tests like this is just very specifically going to test for this, doesn't seem that likely that we'll catch future issues.

wouldn't it be better to just check in a bunch of historic conversations and verify that we can load them?


pub fn deserialize<'de, T, D>(deserializer: D) -> Result<ToolResult<T>, D::Error>
/// Legacy ToolCall format from older sessions (pre-rmcp migration).
/// The old format had `arguments: Value` instead of `arguments: Option<JsonObject>`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to remove the comments here and also not call it just legacy; surely we'll have more changes to formats coming up, representing in the name what's going on here would be better. LegacyToolCallWithValue? longer names beats comments here for sure.

Success { status: String, value: T },
Error { status: String, error: String },
enum ResultFormat {
NewSuccess {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here; New is not going stay that way

@zanesq zanesq merged commit 78a9b5b into main Jan 7, 2026
19 of 20 checks passed
@zanesq zanesq deleted the zane/session-tool-results branch January 7, 2026 23:45
zanesq added a commit that referenced this pull request Jan 8, 2026
* 'main' of github.com:block/goose:
  Fixed fonts (#6389)
  Update confidence levels prompt injection detection to reduce false positive rates (#6390)
  Add ML-based prompt injection detection  (#5623)
  docs: update custom extensions tutorial (#6388)
  fix ResultsFormat error when loading old sessions (#6385)
  docs: add MCP Apps tutorial and documentation updates (#6384)
  changed z-index to make sure the search highlighter does not appear on modal overlay (#6386)
  Handling special claude model response in github copilot provider (#6369)
  fix: prevent duplicate rendering when tool returns both mcp-ui and mcp-apps resources (#6378)
  fix: update MCP Apps _meta.ui.resourceUri to use nested format (SEP-1865) (#6372)
  feat(providers): add streaming support for Google Gemini provider (#6191)
  Blog: edit links in mcp apps post (#6371)
  fix: prevent infinite loop of tool-input notifications in MCP Apps (#6374)
michaelneale added a commit that referenced this pull request Jan 8, 2026
* main: (31 commits)
  added validation and debug for invalid call tool result (#6368)
  Update MCP apps tutorial: fix _meta structure and version prereq (#6404)
  Fixed fonts (#6389)
  Update confidence levels prompt injection detection to reduce false positive rates (#6390)
  Add ML-based prompt injection detection  (#5623)
  docs: update custom extensions tutorial (#6388)
  fix ResultsFormat error when loading old sessions (#6385)
  docs: add MCP Apps tutorial and documentation updates (#6384)
  changed z-index to make sure the search highlighter does not appear on modal overlay (#6386)
  Handling special claude model response in github copilot provider (#6369)
  fix: prevent duplicate rendering when tool returns both mcp-ui and mcp-apps resources (#6378)
  fix: update MCP Apps _meta.ui.resourceUri to use nested format (SEP-1865) (#6372)
  feat(providers): add streaming support for Google Gemini provider (#6191)
  Blog: edit links in mcp apps post (#6371)
  fix: prevent infinite loop of tool-input notifications in MCP Apps (#6374)
  fix: Show platform-specific keyboard shortcuts in UI (#6323)
  fix: we load extensions when agent starts so don't do it up front (#6350)
  docs: credit HumanLayer in RPI tutorial (#6365)
  Blog: Goose Lands MCP Apps (#6172)
  Claude 3.7 is out. we had some harcoded stuff (#6197)
  ...
wpfleger96 added a commit that referenced this pull request Jan 9, 2026
* main: (89 commits)
  fix(google): treat signed text as regular content in streaming (#6400)
  Add frameDomains and baseUriDomains CSP support for MCP Apps (#6399)
  fix(ci): add missing dependencies to openapi-schema-check job (#6367)
  feat: http proxy support
  Add support for changing working dir and extensions in same window/session (#6057)
  Sort keys in canonical models (#6403)
  added validation and debug for invalid call tool result (#6368)
  Update MCP apps tutorial: fix _meta structure and version prereq (#6404)
  Fixed fonts (#6389)
  Update confidence levels prompt injection detection to reduce false positive rates (#6390)
  Add ML-based prompt injection detection  (#5623)
  docs: update custom extensions tutorial (#6388)
  fix ResultsFormat error when loading old sessions (#6385)
  docs: add MCP Apps tutorial and documentation updates (#6384)
  changed z-index to make sure the search highlighter does not appear on modal overlay (#6386)
  Handling special claude model response in github copilot provider (#6369)
  fix: prevent duplicate rendering when tool returns both mcp-ui and mcp-apps resources (#6378)
  fix: update MCP Apps _meta.ui.resourceUri to use nested format (SEP-1865) (#6372)
  feat(providers): add streaming support for Google Gemini provider (#6191)
  Blog: edit links in mcp apps post (#6371)
  ...
wpfleger96 added a commit that referenced this pull request Jan 9, 2026
* main: (89 commits)
  fix(google): treat signed text as regular content in streaming (#6400)
  Add frameDomains and baseUriDomains CSP support for MCP Apps (#6399)
  fix(ci): add missing dependencies to openapi-schema-check job (#6367)
  feat: http proxy support
  Add support for changing working dir and extensions in same window/session (#6057)
  Sort keys in canonical models (#6403)
  added validation and debug for invalid call tool result (#6368)
  Update MCP apps tutorial: fix _meta structure and version prereq (#6404)
  Fixed fonts (#6389)
  Update confidence levels prompt injection detection to reduce false positive rates (#6390)
  Add ML-based prompt injection detection  (#5623)
  docs: update custom extensions tutorial (#6388)
  fix ResultsFormat error when loading old sessions (#6385)
  docs: add MCP Apps tutorial and documentation updates (#6384)
  changed z-index to make sure the search highlighter does not appear on modal overlay (#6386)
  Handling special claude model response in github copilot provider (#6369)
  fix: prevent duplicate rendering when tool returns both mcp-ui and mcp-apps resources (#6378)
  fix: update MCP Apps _meta.ui.resourceUri to use nested format (SEP-1865) (#6372)
  feat(providers): add streaming support for Google Gemini provider (#6191)
  Blog: edit links in mcp apps post (#6371)
  ...
fbalicchia pushed a commit to fbalicchia/goose that referenced this pull request Jan 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants