Skip to content

AttributeError typing.Union object has no attribute __discriminator__ and not __dict__ for setting new attributes #2704

@Natim

Description

@Natim

Confirm this is an issue with the Python library and not an underlying OpenAI API

  • This is an issue with the Python library

Describe the bug

When casting:

cast(CachedDiscriminatorType, union).__discriminator__ = details

With union being:

openai.types.responses.response_audio_delta_event.ResponseAudioDeltaEvent | openai.types.responses.response_audio_done_event.ResponseAudioDoneEvent | openai.types.responses.response_audio_transcript_delta_event.ResponseAudioTranscriptDeltaEvent | openai.types.responses.response_audio_transcript_done_event.ResponseAudioTranscriptDoneEvent | openai.types.responses.response_code_interpreter_call_code_delta_event.ResponseCodeInterpreterCallCodeDeltaEvent | openai.types.responses.response_code_interpreter_call_code_done_event.ResponseCodeInterpreterCallCodeDoneEvent | openai.types.responses.response_code_interpreter_call_completed_event.ResponseCodeInterpreterCallCompletedEvent | openai.types.responses.response_code_interpreter_call_in_progress_event.ResponseCodeInterpreterCallInProgressEvent | openai.types.responses.response_code_interpreter_call_interpreting_event.ResponseCodeInterpreterCallInterpretingEvent | openai.types.responses.response_completed_event.ResponseCompletedEvent | openai.types.responses.response_content_part_added_event.ResponseContentPartAddedEvent | openai.types.responses.response_content_part_done_event.ResponseContentPartDoneEvent | openai.types.responses.response_created_event.ResponseCreatedEvent | openai.types.responses.response_error_event.ResponseErrorEvent | openai.types.responses.response_file_search_call_completed_event.ResponseFileSearchCallCompletedEvent | openai.types.responses.response_file_search_call_in_progress_event.ResponseFileSearchCallInProgressEvent | openai.types.responses.response_file_search_call_searching_event.ResponseFileSearchCallSearchingEvent | openai.types.responses.response_function_call_arguments_delta_event.ResponseFunctionCallArgumentsDeltaEvent | openai.types.responses.response_function_call_arguments_done_event.ResponseFunctionCallArgumentsDoneEvent | openai.types.responses.response_in_progress_event.ResponseInProgressEvent | openai.types.responses.response_failed_event.ResponseFailedEvent | openai.types.responses.response_incomplete_event.ResponseIncompleteEvent | openai.types.responses.response_output_item_added_event.ResponseOutputItemAddedEvent | openai.types.responses.response_output_item_done_event.ResponseOutputItemDoneEvent | openai.types.responses.response_reasoning_summary_part_added_event.ResponseReasoningSummaryPartAddedEvent | openai.types.responses.response_reasoning_summary_part_done_event.ResponseReasoningSummaryPartDoneEvent | openai.types.responses.response_reasoning_summary_text_delta_event.ResponseReasoningSummaryTextDeltaEvent | openai.types.responses.response_reasoning_summary_text_done_event.ResponseReasoningSummaryTextDoneEvent | openai.types.responses.response_reasoning_text_delta_event.ResponseReasoningTextDeltaEvent | openai.types.responses.response_reasoning_text_done_event.ResponseReasoningTextDoneEvent | openai.types.responses.response_refusal_delta_event.ResponseRefusalDeltaEvent | openai.types.responses.response_refusal_done_event.ResponseRefusalDoneEvent | openai.types.responses.response_text_delta_event.ResponseTextDeltaEvent | openai.types.responses.response_text_done_event.ResponseTextDoneEvent | openai.types.responses.response_web_search_call_completed_event.ResponseWebSearchCallCompletedEvent | openai.types.responses.response_web_search_call_in_progress_event.ResponseWebSearchCallInProgressEvent | openai.types.responses.response_web_search_call_searching_event.ResponseWebSearchCallSearchingEvent | openai.types.responses.response_image_gen_call_completed_event.ResponseImageGenCallCompletedEvent | openai.types.responses.response_image_gen_call_generating_event.ResponseImageGenCallGeneratingEvent | openai.types.responses.response_image_gen_call_in_progress_event.ResponseImageGenCallInProgressEvent | openai.types.responses.response_image_gen_call_partial_image_event.ResponseImageGenCallPartialImageEvent | openai.types.responses.response_mcp_call_arguments_delta_event.ResponseMcpCallArgumentsDeltaEvent | openai.types.responses.response_mcp_call_arguments_done_event.ResponseMcpCallArgumentsDoneEvent | openai.types.responses.response_mcp_call_completed_event.ResponseMcpCallCompletedEvent | openai.types.responses.response_mcp_call_failed_event.ResponseMcpCallFailedEvent | openai.types.responses.response_mcp_call_in_progress_event.ResponseMcpCallInProgressEvent | openai.types.responses.response_mcp_list_tools_completed_event.ResponseMcpListToolsCompletedEvent | openai.types.responses.response_mcp_list_tools_failed_event.ResponseMcpListToolsFailedEvent | openai.types.responses.response_mcp_list_tools_in_progress_event.ResponseMcpListToolsInProgressEvent | openai.types.responses.response_output_text_annotation_added_event.ResponseOutputTextAnnotationAddedEvent | openai.types.responses.response_queued_event.ResponseQueuedEvent | openai.types.responses.response_custom_tool_call_input_delta_event.ResponseCustomToolCallInputDeltaEvent | openai.types.responses.response_custom_tool_call_input_done_event.ResponseCustomToolCallInputDoneEvent

And details being:

{'mapping': {'response.audio.delta': <class 'openai.types.responses.response_audio_delta_event.ResponseAudioDeltaEvent'>, 'response.audio.done': <class 'openai.types.responses.response_audio_done_event.ResponseAudioDoneEvent'>, 'response.audio.transcript.delta': <class 'openai.types.responses.response_audio_transcript_delta_event.ResponseAudioTranscriptDeltaEvent'>, 'response.audio.transcript.done': <class 'openai.types.responses.response_audio_transcript_done_event.ResponseAudioTranscriptDoneEvent'>, 'response.code_interpreter_call_code.delta': <class 'openai.types.responses.response_code_interpreter_call_code_delta_event.ResponseCodeInterpreterCallCodeDeltaEvent'>, 'response.code_interpreter_call_code.done': <class 'openai.types.responses.response_code_interpreter_call_code_done_event.ResponseCodeInterpreterCallCodeDoneEvent'>, 'response.code_interpreter_call.completed': <class 'openai.types.responses.response_code_interpreter_call_completed_event.ResponseCodeInterpreterCallCompletedEvent'>, 'response.code_interpreter_call.in_progress': <class 'openai.types.responses.response_code_interpreter_call_in_progress_event.ResponseCodeInterpreterCallInProgressEvent'>, 'response.code_interpreter_call.interpreting': <class 'openai.types.responses.response_code_interpreter_call_interpreting_event.ResponseCodeInterpreterCallInterpretingEvent'>, 'response.completed': <class 'openai.types.responses.response_completed_event.ResponseCompletedEvent'>, 'response.content_part.added': <class 'openai.types.responses.response_content_part_added_event.ResponseContentPartAddedEvent'>, 'response.content_part.done': <class 'openai.types.responses.response_content_part_done_event.ResponseContentPartDoneEvent'>, 'response.created': <class 'openai.types.responses.response_created_event.ResponseCreatedEvent'>, 'error': <class 'openai.types.responses.response_error_event.ResponseErrorEvent'>, 'response.file_search_call.completed': <class 'openai.types.responses.response_file_search_call_completed_event.ResponseFileSearchCallCompletedEvent'>, 'response.file_search_call.in_progress': <class 'openai.types.responses.response_file_search_call_in_progress_event.ResponseFileSearchCallInProgressEvent'>, 'response.file_search_call.searching': <class 'openai.types.responses.response_file_search_call_searching_event.ResponseFileSearchCallSearchingEvent'>, 'response.function_call_arguments.delta': <class 'openai.types.responses.response_function_call_arguments_delta_event.ResponseFunctionCallArgumentsDeltaEvent'>, 'response.function_call_arguments.done': <class 'openai.types.responses.response_function_call_arguments_done_event.ResponseFunctionCallArgumentsDoneEvent'>, 'response.in_progress': <class 'openai.types.responses.response_in_progress_event.ResponseInProgressEvent'>, 'response.failed': <class 'openai.types.responses.response_failed_event.ResponseFailedEvent'>, 'response.incomplete': <class 'openai.types.responses.response_incomplete_event.ResponseIncompleteEvent'>, 'response.output_item.added': <class 'openai.types.responses.response_output_item_added_event.ResponseOutputItemAddedEvent'>, 'response.output_item.done': <class 'openai.types.responses.response_output_item_done_event.ResponseOutputItemDoneEvent'>, 'response.reasoning_summary_part.added': <class 'openai.types.responses.response_reasoning_summary_part_added_event.ResponseReasoningSummaryPartAddedEvent'>, 'response.reasoning_summary_part.done': <class 'openai.types.responses.response_reasoning_summary_part_done_event.ResponseReasoningSummaryPartDoneEvent'>, 'response.reasoning_summary_text.delta': <class 'openai.types.responses.response_reasoning_summary_text_delta_event.ResponseReasoningSummaryTextDeltaEvent'>, 'response.reasoning_summary_text.done': <class 'openai.types.responses.response_reasoning_summary_text_done_event.ResponseReasoningSummaryTextDoneEvent'>, 'response.reasoning_text.delta': <class 'openai.types.responses.response_reasoning_text_delta_event.ResponseReasoningTextDeltaEvent'>, 'response.reasoning_text.done': <class 'openai.types.responses.response_reasoning_text_done_event.ResponseReasoningTextDoneEvent'>, 'response.refusal.delta': <class 'openai.types.responses.response_refusal_delta_event.ResponseRefusalDeltaEvent'>, 'response.refusal.done': <class 'openai.types.responses.response_refusal_done_event.ResponseRefusalDoneEvent'>, 'response.output_text.delta': <class 'openai.types.responses.response_text_delta_event.ResponseTextDeltaEvent'>, 'response.output_text.done': <class 'openai.types.responses.response_text_done_event.ResponseTextDoneEvent'>, 'response.web_search_call.completed': <class 'openai.types.responses.response_web_search_call_completed_event.ResponseWebSearchCallCompletedEvent'>, 'response.web_search_call.in_progress': <class 'openai.types.responses.response_web_search_call_in_progress_event.ResponseWebSearchCallInProgressEvent'>, 'response.web_search_call.searching': <class 'openai.types.responses.response_web_search_call_searching_event.ResponseWebSearchCallSearchingEvent'>, 'response.image_generation_call.completed': <class 'openai.types.responses.response_image_gen_call_completed_event.ResponseImageGenCallCompletedEvent'>, 'response.image_generation_call.generating': <class 'openai.types.responses.response_image_gen_call_generating_event.ResponseImageGenCallGeneratingEvent'>, 'response.image_generation_call.in_progress': <class 'openai.types.responses.response_image_gen_call_in_progress_event.ResponseImageGenCallInProgressEvent'>, 'response.image_generation_call.partial_image': <class 'openai.types.responses.response_image_gen_call_partial_image_event.ResponseImageGenCallPartialImageEvent'>, 'response.mcp_call_arguments.delta': <class 'openai.types.responses.response_mcp_call_arguments_delta_event.ResponseMcpCallArgumentsDeltaEvent'>, 'response.mcp_call_arguments.done': <class 'openai.types.responses.response_mcp_call_arguments_done_event.ResponseMcpCallArgumentsDoneEvent'>, 'response.mcp_call.completed': <class 'openai.types.responses.response_mcp_call_completed_event.ResponseMcpCallCompletedEvent'>, 'response.mcp_call.failed': <class 'openai.types.responses.response_mcp_call_failed_event.ResponseMcpCallFailedEvent'>, 'response.mcp_call.in_progress': <class 'openai.types.responses.response_mcp_call_in_progress_event.ResponseMcpCallInProgressEvent'>, 'response.mcp_list_tools.completed': <class 'openai.types.responses.response_mcp_list_tools_completed_event.ResponseMcpListToolsCompletedEvent'>, 'response.mcp_list_tools.failed': <class 'openai.types.responses.response_mcp_list_tools_failed_event.ResponseMcpListToolsFailedEvent'>, 'response.mcp_list_tools.in_progress': <class 'openai.types.responses.response_mcp_list_tools_in_progress_event.ResponseMcpListToolsInProgressEvent'>, 'response.output_text.annotation.added': <class 'openai.types.responses.response_output_text_annotation_added_event.ResponseOutputTextAnnotationAddedEvent'>, 'response.queued': <class 'openai.types.responses.response_queued_event.ResponseQueuedEvent'>, 'response.custom_tool_call_input.delta': <class 'openai.types.responses.response_custom_tool_call_input_delta_event.ResponseCustomToolCallInputDeltaEvent'>, 'response.custom_tool_call_input.done': <class 'openai.types.responses.response_custom_tool_call_input_done_event.ResponseCustomToolCallInputDoneEvent'>}, 'field_name': 'type', 'field_alias_from': None}

To Reproduce

CachedDiscriminatorType should be an Annotated rather than Union directly.

Annotated[openai.types.responses.response_audio_delta_event.ResponseAudioDeltaEvent | openai.types.responses.response_audio_done_event.ResponseAudioDoneEvent | openai.types.responses.response_audio_transcript_delta_event.ResponseAudioTranscriptDeltaEvent | openai.types.responses.response_audio_transcript_done_event.ResponseAudioTranscriptDoneEvent | openai.types.responses.response_code_interpreter_call_code_delta_event.ResponseCodeInterpreterCallCodeDeltaEvent | openai.types.responses.response_code_interpreter_call_code_done_event.ResponseCodeInterpreterCallCodeDoneEvent | openai.types.responses.response_code_interpreter_call_completed_event.ResponseCodeInterpreterCallCompletedEvent | openai.types.responses.response_code_interpreter_call_in_progress_event.ResponseCodeInterpreterCallInProgressEvent | openai.types.responses.response_code_interpreter_call_interpreting_event.ResponseCodeInterpreterCallInterpretingEvent | openai.types.responses.response_completed_event.ResponseCompletedEvent | openai.types.responses.response_content_part_added_event.ResponseContentPartAddedEvent | openai.types.responses.response_content_part_done_event.ResponseContentPartDoneEvent | openai.types.responses.response_created_event.ResponseCreatedEvent | openai.types.responses.response_error_event.ResponseErrorEvent | openai.types.responses.response_file_search_call_completed_event.ResponseFileSearchCallCompletedEvent | openai.types.responses.response_file_search_call_in_progress_event.ResponseFileSearchCallInProgressEvent | openai.types.responses.response_file_search_call_searching_event.ResponseFileSearchCallSearchingEvent | openai.types.responses.response_function_call_arguments_delta_event.ResponseFunctionCallArgumentsDeltaEvent | openai.types.responses.response_function_call_arguments_done_event.ResponseFunctionCallArgumentsDoneEvent | openai.types.responses.response_in_progress_event.ResponseInProgressEvent | openai.types.responses.response_failed_event.ResponseFailedEvent | openai.types.responses.response_incomplete_event.ResponseIncompleteEvent | openai.types.responses.response_output_item_added_event.ResponseOutputItemAddedEvent | openai.types.responses.response_output_item_done_event.ResponseOutputItemDoneEvent | openai.types.responses.response_reasoning_summary_part_added_event.ResponseReasoningSummaryPartAddedEvent | openai.types.responses.response_reasoning_summary_part_done_event.ResponseReasoningSummaryPartDoneEvent | openai.types.responses.response_reasoning_summary_text_delta_event.ResponseReasoningSummaryTextDeltaEvent | openai.types.responses.response_reasoning_summary_text_done_event.ResponseReasoningSummaryTextDoneEvent | openai.types.responses.response_reasoning_text_delta_event.ResponseReasoningTextDeltaEvent | openai.types.responses.response_reasoning_text_done_event.ResponseReasoningTextDoneEvent | openai.types.responses.response_refusal_delta_event.ResponseRefusalDeltaEvent | openai.types.responses.response_refusal_done_event.ResponseRefusalDoneEvent | openai.types.responses.response_text_delta_event.ResponseTextDeltaEvent | openai.types.responses.response_text_done_event.ResponseTextDoneEvent | openai.types.responses.response_web_search_call_completed_event.ResponseWebSearchCallCompletedEvent | openai.types.responses.response_web_search_call_in_progress_event.ResponseWebSearchCallInProgressEvent | openai.types.responses.response_web_search_call_searching_event.ResponseWebSearchCallSearchingEvent | openai.types.responses.response_image_gen_call_completed_event.ResponseImageGenCallCompletedEvent | openai.types.responses.response_image_gen_call_generating_event.ResponseImageGenCallGeneratingEvent | openai.types.responses.response_image_gen_call_in_progress_event.ResponseImageGenCallInProgressEvent | openai.types.responses.response_image_gen_call_partial_image_event.ResponseImageGenCallPartialImageEvent | openai.types.responses.response_mcp_call_arguments_delta_event.ResponseMcpCallArgumentsDeltaEvent | openai.types.responses.response_mcp_call_arguments_done_event.ResponseMcpCallArgumentsDoneEvent | openai.types.responses.response_mcp_call_completed_event.ResponseMcpCallCompletedEvent | openai.types.responses.response_mcp_call_failed_event.ResponseMcpCallFailedEvent | openai.types.responses.response_mcp_call_in_progress_event.ResponseMcpCallInProgressEvent | openai.types.responses.response_mcp_list_tools_completed_event.ResponseMcpListToolsCompletedEvent | openai.types.responses.response_mcp_list_tools_failed_event.ResponseMcpListToolsFailedEvent | openai.types.responses.response_mcp_list_tools_in_progress_event.ResponseMcpListToolsInProgressEvent | openai.types.responses.response_output_text_annotation_added_event.ResponseOutputTextAnnotationAddedEvent | openai.types.responses.response_queued_event.ResponseQueuedEvent | openai.types.responses.response_custom_tool_call_input_delta_event.ResponseCustomToolCallInputDeltaEvent | openai.types.responses.response_custom_tool_call_input_done_event.ResponseCustomToolCallInputDoneEvent, discriminator="type")
Image

Code snippets

OS

ubuntu

Python version

Python v3.14.0

Library version

openai v2.6.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions