fix(tracing): prevent RecursionError in truncation of truncated previews#2857
fix(tracing): prevent RecursionError in truncation of truncated previews#2857Bahtya wants to merge 3 commits intoopenai:mainfrom
Conversation
When _truncated_preview() returns a dict like {"truncated": True, ...},
_truncate_json_value_for_limit treats it as a regular dict and calls
_truncate_mapping_for_json_limit again. The bool value "True" gets
wrapped into another preview dict, which itself gets re-truncated,
causing infinite recursion.
Fix: detect truncated preview dicts and return them immediately without
re-processing.
Fixes openai#2856
Signed-off-by: bahtya <bahtyar153@qq.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a2b12180da
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
src/agents/tracing/processors.py
Outdated
| if value.get("truncated") is True and "original_type" in value and "preview" in value: | ||
| return value |
There was a problem hiding this comment.
Narrow truncated-preview detection to SDK-generated shape
The early return in _truncate_json_value_for_limit now treats any dict with truncated=True, original_type, and preview as an internal preview object and skips truncation. If user-provided span data legitimately uses those keys and also contains large additional fields, root-level truncation returns the oversized dict unchanged, which can exceed _OPENAI_TRACING_MAX_FIELD_BYTES and cause export rejection or dropped tracing data. This check should only bypass truncation for SDK-created preview dicts (for example by requiring the exact key set or using a dedicated sentinel).
Useful? React with 👍 / 👎.
Address review feedback: using key-based detection (truncated, original_type, preview) could match arbitrary user data that happens to use the same key names, potentially bypassing truncation for oversized dicts. Add a __truncated_preview__ sentinel key to SDK-generated preview dicts so only our own previews are short-circuited. Signed-off-by: bahtya <bahtyar153@qq.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95620cadc9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
src/agents/tracing/processors.py
Outdated
| if self._TRUNCATED_PREVIEW_KEY in value: | ||
| return value |
There was a problem hiding this comment.
Validate sentinel value before skipping dict truncation
Fresh evidence: the new guard now returns early for any mapping that merely contains __truncated_preview__, regardless of its value or shape. If user span data includes that key (for example {"__truncated_preview__": false, ...}) and the field exceeds _OPENAI_TRACING_MAX_FIELD_BYTES, _truncate_json_value_for_limit will return the oversized dict unchanged, which can still be rejected by tracing export limits and drop trace content. Restrict the bypass to SDK-generated preview objects (for example, require value.get(__truncated_preview__) is True plus expected preview fields).
Useful? React with 👍 / 👎.
Address second review feedback: checking only for the sentinel key presence could still match user data that includes __truncated_preview__ as a key. Now also verify the value is True and expected preview fields (original_type, preview) are present. Signed-off-by: bahtya <bahtyar153@qq.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f6163df254
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if value.get(self._TRUNCATED_PREVIEW_KEY) is True and "original_type" in value and "preview" in value: | ||
| return value |
There was a problem hiding this comment.
Restrict preview bypass to SDK-owned objects
Fresh evidence: although this guard now also checks original_type and preview, it still short-circuits on any user-supplied dict that includes "__truncated_preview__": true and those keys. If that dict also contains large extra fields and exceeds _OPENAI_TRACING_MAX_FIELD_BYTES, _truncate_json_value_for_limit returns it unchanged instead of delegating to _truncate_mapping_for_json_limit, so sanitization can still emit oversized span fields that get rejected or dropped by trace ingestion.
Useful? React with 👍 / 👎.
|
Thanks for trying to resolve the issue. I came up with an alternative one for this, and it should work well: #2860 |
|
Closing this in favor of #2860 |
Problem
When LLM responses contain
Nonevalues and need truncation,_truncate_json_value_for_limitcrashes withRecursionError. The truncation logic re-processes its own preview dicts, creating an infinite loop.Root Cause
_truncated_preview()returns{"truncated": True, "original_type": "NoneType", "preview": "..."}_truncate_json_value_for_limit()treats this as a regular dict → calls_truncate_mapping_for_json_limit()Truebool value gets wrapped by_truncated_preview(True)into yet another dictSolution
Detect truncated preview dicts (have
"truncated": True,"original_type","preview"keys) and return them immediately without re-processing.Fixes #2856