bug(openai): a stream that fails mid-iteration ends the generation without level ERROR
Les mainteneurs répondent en général sous 1 jour
Évaluation
Cette issue n'a pas encore été évaluée.
Description
Describe the bug
When an OpenAI chat stream fails after the first chunk, the generation ends with no level and no status_message. The caller gets openai.APIError, while Langfuse shows a normal generation holding the partial output. The same failure before the stream starts is recorded as ERROR.
The cause is in langfuse/openai.py. _wrap catches only what create() raises. Exceptions raised while iterating go through traced_iterator's finally (line 1112) into _finalize_stream_response, which calls generation.end() with no error. The async path (_instrument_openai_async_stream) and LangfuseResponseGeneratorSync/Async do the same.
To reproduce
import httpx
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
from langfuse import Langfuse
from langfuse.openai import OpenAI
exporter = InMemorySpanExporter()
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(exporter))
Langfuse(public_key="pk", secret_key="sk", base_url="http://127.0.0.1:9", tracer_provider=provider)
SSE = (
b'data: {"id":"c1","object":"chat.completion.chunk","created":1,"model":"gpt-4o-mini",'
b'"choices":[{"index":0,"delta":{"role":"assistant","content":"Hel"},"finish_reason":null}]}\n\n'
b'data: {"error":{"message":"The server had an error while processing your request.","type":"server_error"}}\n\n'
)
client = OpenAI(api_key="x", http_client=httpx.Client(transport=httpx.MockTransport(
lambda r: httpx.Response(200, headers={"content-type": "text/event-stream"}, content=SSE))))
stream = client.chat.completions.create(name="failed-stream", model="gpt-4o-mini",
messages=[{"role": "user", "content": "hi"}], stream=True)
try:
for chunk in stream:
pass
except Exception as e:
print("caller saw :", type(e).__name__, e)
a = next(s for s in exporter.get_finished_spans() if s.name == "failed-stream").attributes
print("level :", a.get("langfuse.observation.level"))
print("status_msg :", a.get("langfuse.observation.status_message"))
print("output :", a.get("langfuse.observation.output"))
$ python lf_stream_error.py 2>/dev/null
caller saw : APIError The server had an error while processing your request.
level : None
status_msg : None
output : Hel
With the transport answering 500 to create(stream=True) instead, the generation records ERROR | Error code: 500 - {'error': {'message': 'server_error'}}. The AsyncOpenAI version of the failing stream also prints level: None.
Expected
level="ERROR" and status_message=str(error) on the generation, with the partial output and any usage kept. The OpenAI integration docs say Langfuse "automatically tracks and monitors OpenAI API errors" in level and statusMessage, and test_chat_completion_error_marks_generation_error pins that for the non-streaming case.
SDK versions
langfuse 5.0.2 at 81c457c, openai 3.35.1, opentelemetry-sdk 1.45.1, Python 3.12. Not checked: the Responses API, where a response.failed event raises nothing.
@hassiebp I'd catch the exception in each iterator wrapper, set the error on the generation, and re-raise. A test using the SSE body above can live next to the existing break test in tests/unit/test_openai.py. Shall I open that PR?
- Langage dominant
- Python
- Étoiles
- 502
- Forks
- 381
- Merge moyen
- 1 j 1 h
- PR mergées (30 j)
- 64
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de langfuse/langfuse-python
-
bug(scores): create_score sends numpy.bool_ as JSON `true` and Decimal as "<Decimal>" since v5.0.2Peut-être pris @lalith0407 l’a pris il y a 3 jours. Ouvertebug feat-scores sdk-python
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
langfuse/langfuse-python#2057 ·
Les mainteneurs répondent en général sous 1 jour
-
tests/unit/test_prompt.py fails on a fresh clone without LANGFUSE_* env varsPeut-être pris @Mathoholic l’a pris il y a 17 jours. Ouvertebug feat-prompt-management sdk-python
Difficulté 2/5 1-3 heures Accessibilité débutants 80/100
langfuse/langfuse-python#1976 · 3 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
fix(serializer): handle single-string __slots__ and detect cycles in slotted objectsPeut-être pris @hassiebp l’a pris il y a 12 jours. Ouvertebug sdk-python
langfuse/langfuse-python#2014 · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder itemPeut-être pris @nimarb l’a pris il y a 7 jours. Ouvertebug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
bug: GCS upload detection in MediaManager uses substring match on the full URLPeut-être pris @hassiebp l’a pris il y a 27 jours. Ouvertebug feat-multimodal-media sdk-python
langfuse/langfuse-python#1913 · 1 commentaire · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de langfuse/langfuse-python
Issues similaires
-
difficulty:2 enhancement good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
MakazhanAlpamys/Soup#2309 ·
Les mainteneurs répondent en général sous 1 jour
-
TAPVid-3D: per_trajectory and local_neighborhood scaling always score 0 in evaluate_model.pyOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
google-deepmind/tapnet#173 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
-
change-description-authoring: jdk-33173-audit check 4 grades the hunk translation by its verbOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
Netcracker/qubership-ai-packages#203 ·
Les mainteneurs répondent en général sous 1 jour
-
PAC Wording
Difficulté 1/5 Moins d'une heure Accessibilité débutants 72/100
Les mainteneurs répondent en général sous 1 jour