Skip to content

🐛 Bug Report: 'Omit' object has no attribute 'get' in responses_wrappers.py #3472

@alexey-pelykh

Description

@alexey-pelykh

Description

The OpenAI instrumentation crashes when the OpenAI SDK's Omit sentinel value is passed as a parameter. The instrumentation attempts to call .get() on request kwargs, but Omit objects don't have that method.

Error

AttributeError: 'Omit' object has no attribute 'get'

Stack Trace (minimal)

File "opentelemetry/instrumentation/openai/v1/responses_wrappers.py", line 789, in __init__
    request_reasoning_summary=self._request_kwargs.get("reasoning", {}).get(
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Omit' object has no attribute 'get'

Root Cause

The OpenAI Python SDK uses Omit as a sentinel type for unset optional parameters. When calling responses.create() with default parameters like reasoning=omit:

  1. kwargs.get("reasoning", {}) returns the Omit object (not {}) because the key exists with the sentinel value
  2. Then .get("summary", ...) fails because Omit doesn't have a .get() method

Reproduction

import asyncio
from openai import AsyncOpenAI
from opentelemetry.instrumentation.openai import OpenAIInstrumentor

OpenAIInstrumentor().instrument()

async def main():
    client = AsyncOpenAI()
    # Crashes because reasoning defaults to `omit`
    async with await client.responses.create(
        model="gpt-4o",
        input="Hello",
        stream=True,
    ) as stream:
        async for event in stream:
            print(event)

asyncio.run(main())

Environment

  • Python: 3.13
  • openai: 2.8.1
  • opentelemetry-instrumentation-openai: 0.48.1

Suggested Fix

Add a helper function for safe nested dict access:

from typing import Any

def _get_dict_value(obj: Any, key: str, default: Any = None) -> Any:
    """Safely get value from dict-like object, returning default for non-dict types."""
    if isinstance(obj, dict):
        return obj.get(key, default)
    return default

Usage:

reasoning = self._request_kwargs.get("reasoning")
request_reasoning_summary = _get_dict_value(
    reasoning, "summary", existing_data.get("request_reasoning_summary")
)

This pattern should be applied to all similar kwargs access in responses_wrappers.py.

Workaround

Monkey-patching Omit to add a .get() method:

from openai import Omit

if not hasattr(Omit, "get"):
    Omit.get = lambda self, key, default=None: default

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions