Skip to content

Python: Reject oversized MessagePack history records before writing - #9260

Merged
Eduard van Valkenburg (eavanvalkenburg) merged 4 commits into
microsoft:mainfrom
ShivamSharma43:fix/8633-msgpack-oversized-record
Oct 26, 2026
Merged

Eduard van Valkenburg (eavanvalkenburg) merged 4 commits into
microsoft:mainfrom
ShivamSharma43:fix/8633-msgpack-oversized-record

Conversation

@ShivamSharma43

Copy link
Copy Markdown
Contributor

Motivation & Context

FileHistoryProvider(serialization_format="msgpack") can save a record that its own reader refuses to load. _read_msgpack_messages() rejects records longer than _MAX_MSGPACK_RECORD_BYTES (64 MiB), but save_messages() appended them without checking. After one oversized message, get_messages() raises ValueError for that session, and every later save_messages() fails the same way because it reads the existing history for deduplication first. A single large inline media payload can make an otherwise valid conversation unusable.

Description & Review Guide

  • What are the major changes? In the MessagePack branch of FileHistoryProvider.save_messages(), the batch of new messages is now encoded up front, and each record is checked against _MAX_MSGPACK_RECORD_BYTES before the file is opened. An oversized record raises ValueError naming its size and the limit. Records are then written from the already-encoded bytes, so each message is encoded once.
  • What is the impact of these changes? A rejected batch leaves the history file untouched, including when the oversized record comes after a valid one in the same batch, so the session stays loadable and the save can be retried with a smaller payload. Records exactly at the limit are still accepted, which matches the reader's > limit check. JSON Lines storage and successful MessagePack saves are unchanged.
  • What do you want reviewers to focus on? Whether raising ValueError from save_messages() is the right signal here. It matches what get_messages() already raises for the same record.

Tests added in tests/core/test_sessions.py, using a lowered limit so no large payloads are allocated:

  • test_msgpack_rejects_oversized_batch_without_mutating_history: a batch of a valid record followed by an oversized one is rejected, the file bytes are unchanged, the session still loads, and saving the valid record afterwards works. It fails without the fix.
  • test_msgpack_record_at_size_limit_round_trips: a record exactly at the limit saves and loads.

Related Issue

Fixes #8633

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

🤖 Generated with Claude Code

FileHistoryProvider(serialization_format="msgpack") appended records larger
than the 64 MiB limit that its reader enforces, so one oversized message made
the session unreadable, and every later save failed too because it reads the
history for deduplication first. Encode and check the whole batch before
opening the file, so a rejected batch leaves the existing history untouched
and the call can be retried.

Fixes microsoft#8633

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Oct 11, 2026
@eavanvalkenburg

Copy link
Copy Markdown
Member

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

MAF Automated Review — Iteration 1

Result: Findings reported
Scope: full PR (1 commit(s)): 25740710f8e9
Model: gpt-5.6-sol

Overview

The change correctly aligns MessagePack writes with the reader's per-record limit and validates the complete batch before opening the file, with tests covering rollback and the exact-limit boundary. Existing locking, deduplication, and error propagation preserve the intended history contract. However, the preflight materializes every encoded record at once, so an unbounded batch can exhaust shared process memory even when every individual record is valid.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.

Affected areas: python/packages/core/agent_framework/_sessions.py

Comment thread python/packages/core/agent_framework/_sessions.py Outdated
The size preflight kept every encoded record of the batch, so memory grew
with batch length. Encode each record into one reused buffer, once to check
the size and once to write, so memory is bounded by the largest record. The
batch is still rejected as a whole before the file is opened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@eavanvalkenburg

Copy link
Copy Markdown
Member

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

MAF Automated Review — Iteration 2

Result: Findings reported
Scope: 1 net-new commit(s): 73cd27c751ae
Model: gpt-5.6-sol

Overview

This incremental change replaces batch-wide encoded-record retention with a reusable buffer, and its regression test confirms that memory no longer scales with batch length. The existing preflight, exact-limit test, and reader-side length guard remain strong defenses. However, the write pass serializes each mutable message again without validating the bytes actually persisted, which can recreate the oversized-record corruption this PR is intended to prevent.

Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.

Affected areas: python/packages/core/agent_framework/_sessions.py

Comment thread python/packages/core/agent_framework/_sessions.py Outdated
… on failure

The preflight checked the first encoding of each message, but the write
pass encoded it again and wrote that result unchecked. A message whose
to_dict() changes between the passes could still append a record the
reader rejects. The write pass now checks each record before writing it,
and any failure truncates the file back to where this call started
appending, so the history stays loadable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged via the queue into microsoft:main with commit 5b78076 Oct 26, 2026
48 checks passed

This branch was previously deployed

1 inactive deployment
github-app-auth — cbe6e6e2 Deployed Oct 15, 2026 by ShivamSharma43 via add_label #25404
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Oversized MessagePack history records make sessions unreadable

3 participants