{"record":{"id":"cf87d768af42c7e8","repo":"openai/openai-python","slug":"a-single-event-handler-cannot-be-shared-between-mu","errorCode":null,"errorMessage":"A single event handler cannot be shared between multiple streams; You will need to construct a new event handler instance","messagePattern":"A single event handler cannot be shared between multiple streams; You will need to construct a new event handler instance","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/openai/lib/streaming/_assistants.py","lineNumber":63,"sourceCode":"    def __init__(self) -> None:\n        self._current_event: AssistantStreamEvent | None = None\n        self._current_message_content_index: int | None = None\n        self._current_message_content: MessageContent | None = None\n        self._current_tool_call_index: int | None = None\n        self._current_tool_call: ToolCall | None = None\n        self.__current_run_step_id: str | None = None\n        self.__current_run: Run | None = None\n        self.__run_step_snapshots: dict[str, RunStep] = {}\n        self.__message_snapshots: dict[str, Message] = {}\n        self.__current_message_snapshot: Message | None = None\n\n        self.text_deltas = self.__text_deltas__()\n        self._iterator = self.__stream__()\n        self.__stream: Stream[AssistantStreamEvent] | None = None\n\n    def _init(self, stream: Stream[AssistantStreamEvent]) -> None:\n        if self.__stream:\n            raise RuntimeError(\n                \"A single event handler cannot be shared between multiple streams; You will need to construct a new event handler instance\"\n            )\n\n        self.__stream = stream\n\n    def __next__(self) -> AssistantStreamEvent:\n        return self._iterator.__next__()\n\n    def __iter__(self) -> Iterator[AssistantStreamEvent]:\n        for item in self._iterator:\n            yield item\n\n    @property\n    def current_event(self) -> AssistantStreamEvent | None:\n        return self._current_event\n\n    @property\n    def current_run(self) -> Run | None:","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/openai/openai-python/blob/9917c6e28e66e90e1227b3d223c06a8c5441515a/src/openai/lib/streaming/_assistants.py#L45-L81","documentation":"This RuntimeError is thrown by AssistantEventHandler._init when the same handler instance is passed to a second streaming call. The handler stores per-stream state (the Stream reference, accumulated snapshots, iterators created in __init__), so entering a new stream with an already-bound handler would mix state from two runs. The library therefore forbids reuse after the handler has been entered via __enter__/__aenter__.","triggerScenarios":"Calling client.beta.threads.runs.stream(...) (or create_and_stream) twice with the same AssistantEventHandler instance, e.g. in a loop: for q in questions: with client.beta.threads.runs.stream(thread_id=..., assistant_id=..., event_handler=handler). Any second stream entered with a handler whose _init already ran will raise.","commonSituations":"Retrying or looping over multiple user questions with one handler; sharing a module-level handler; partial-migration from the old Assistants streaming API where reuse appeared to work; forgetting that entering the handler in a with-block binds it permanently.","solutions":["Construct a fresh AssistantEventHandler (or subclass) instance for every stream call","If you loop over prompts, move handler construction inside the loop","If you need shared logic, put it in the handler class (override on_event etc.) rather than sharing one instance","Check that you are not accidentally passing the same handler to both a retry and the original call"],"exampleFix":"# before\nhandler = MyHandler()\nfor question in questions:\n    with client.beta.threads.runs.stream(thread_id=..., assistant_id=..., event_handler=handler) as stream:\n        stream.until_done()\n\n# after\nfor question in questions:\n    handler = MyHandler()  # new instance per stream\n    with client.beta.threads.runs.stream(thread_id=..., assistant_id=..., event_handler=handler) as stream:\n        stream.until_done()","handlingStrategy":"validation","validationCode":"def assert_fresh_handler(handler) -> None:\n    if getattr(handler, \"_AssistantEventHandler__stream\", None):\n        raise RuntimeError(\"handler already bound to a previous stream; construct a new one\")","typeGuard":"def is_unbound_handler(h: AssistantEventHandler) -> bool:\n    return getattr(h, \"_AssistantEventHandler__stream\", None) is None","tryCatchPattern":"try:\n    with client.beta.threads.runs.stream(..., event_handler=handler) as s:\n        s.until_done()\nexcept RuntimeError as e:\n    if \"cannot be shared\" in str(e):\n        handler = MyHandler()  # fresh instance, then retry once","preventionTips":["Instantiate one handler per stream call, inside loops/request scopes","Keep per-request state off shared handler objects","Wrap handler construction near the stream call site"],"tags":["assistants","streaming","event-handler","reuse","python"],"backgroundTag":"stream-handler-reuse","analyzedSha":"9917c6e28e66e90e1227b3d223c06a8c5441515a","analyzedAt":"2026-08-28T11:46:34.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}