Skip to content

Backport #4492 to release/3.x: don't mutate the caller's schema in compress_schema - #4663

Merged
jlowin merged 4 commits into
release/3.xfrom
backport/4492-compress-schema-mutation
Jul 27, 2026
Merged

jlowin merged 4 commits into
release/3.xfrom
backport/4492-compress-schema-mutation

Conversation

@jlowin

@jlowin jlowin commented Jul 27, 2026 •

Copy link
Copy Markdown
Member

Backport of #4492 to release/3.x for the 3.4.5 patch release. Closes #4493 on the 3.x line.

compress_schema() documented that it returns a new schema and leaves its input untouched, but its pruning phases popped title, additionalProperties, and unused $defs off the dict the caller passed in. Callers sharing a schema across components could see one component's compression silently alter another's.

Codex review on this PR caught that the deepcopy fixing that mutation introduces a recursion ceiling: a schema nested a few hundred levels deep now raises RecursionError before the traversal's own depth > 50 guard can return a partially optimized schema. Chasing that surfaced a second, older problem — the reference scan stops at that same guard, but the pruning phase treats every definition it did not see referenced as unused, so a $ref below the cutoff had its $defs entry deleted out from under it.

This carries both fixes across alongside the original backport, so 3.4.5 ships the fix without the regression:

  • _copy_schema walks the schema with an explicit stack instead of recursing, so the copy no longer sets a depth ceiling.
  • $defs pruning is skipped whenever the reference scan was truncated. An unpruned definition is harmless; a dangling $ref is an invalid schema.

The dangling-reference bug is not specific to this backport — it reproduces on release/3.x today at 60 levels of nesting, well within what deepcopy handled.

Upstream on main as #4671.

@marvin-context-protocol marvin-context-protocol Bot added the bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. label Jul 27, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7bcbb31298

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# Work on a copy so the caller's schema is never mutated (see docstring). The
# pruning phases below pop keys/$defs in place, which would otherwise corrupt a
# shared dict such as a live Tool.input_schema passed straight to compress_schema.
schema = copy.deepcopy(schema)

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.

P2 Badge Preserve the depth guard when copying schemas

When compress_schema receives a valid schema with roughly 500 nested items objects under Python's default recursion limit, this deepcopy raises RecursionError before traverse_and_clean can reach its existing depth > 50 guard; the parent implementation returned normally by stopping at that guard. Deep schemas from remote or proxied MCP tools will therefore fail compression instead of returning a partially optimized schema, so the copy should be performed iteratively or otherwise honor the same bounded-recursion behavior.

Useful? React with 👍 / 👎.

@jlowin
jlowin merged commit 5daa91b into release/3.x Jul 27, 2026
11 checks passed
@jlowin
jlowin deleted the backport/4492-compress-schema-mutation branch July 27, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants