Skip to content

fix(tracing): prevent RecursionError in truncation of truncated previews#2857

Closed
Bahtya wants to merge 3 commits intoopenai:mainfrom
Bahtya:fix/truncation-recursion
Closed

fix(tracing): prevent RecursionError in truncation of truncated previews#2857
Bahtya wants to merge 3 commits intoopenai:mainfrom
Bahtya:fix/truncation-recursion

Conversation

@Bahtya
Copy link
Copy Markdown

@Bahtya Bahtya commented Apr 8, 2026

Problem

When LLM responses contain None values and need truncation, _truncate_json_value_for_limit crashes with RecursionError. The truncation logic re-processes its own preview dicts, creating an infinite loop.

Root Cause

  1. _truncated_preview() returns {"truncated": True, "original_type": "NoneType", "preview": "..."}
  2. _truncate_json_value_for_limit() treats this as a regular dict → calls _truncate_mapping_for_json_limit()
  3. The True bool value gets wrapped by _truncated_preview(True) into yet another dict
  4. This new dict is again treated as a regular mapping → infinite recursion

Solution

Detect truncated preview dicts (have "truncated": True, "original_type", "preview" keys) and return them immediately without re-processing.

if value.get("truncated") is True and "original_type" in value and "preview" in value:
    return value

Fixes #2856

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>
@github-actions github-actions bot added bug Something isn't working feature:tracing labels Apr 8, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 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".

Comment on lines +297 to +298
if value.get("truncated") is True and "original_type" in value and "preview" in value:
return value
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 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".

Comment on lines +302 to +303
if self._TRUNCATED_PREVIEW_KEY in value:
return value
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 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".

Comment on lines +302 to +303
if value.get(self._TRUNCATED_PREVIEW_KEY) is True and "original_type" in value and "preview" in value:
return value
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@seratch
Copy link
Copy Markdown
Member

seratch commented Apr 8, 2026

Thanks for trying to resolve the issue. I came up with an alternative one for this, and it should work well: #2860

@seratch seratch marked this pull request as draft April 8, 2026 11:06
@seratch
Copy link
Copy Markdown
Member

seratch commented Apr 8, 2026

Closing this in favor of #2860

@seratch seratch closed this Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working feature:tracing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RecursionError in tracing truncation: preview dict recursively re-truncated when message content is None

2 participants