bug(openai): a stream that fails mid-iteration ends the generation without level ERROR
Los mantenedores suelen responder en 1 día
Evaluación
Este issue todavía no se ha evaluado.
Descripción
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?
- Lenguaje dominante
- Python
- Estrellas
- 504
- Forks
- 391
- Merge medio
- 1 d 1 h
- PR fusionados (30 d)
- 64
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de langfuse/langfuse-python
-
bug(scores): create_score sends numpy.bool_ as JSON `true` and Decimal as "<Decimal>" since v5.0.2Posiblemente ocupada @lalith0407 la tomó hace 4 días. Abiertobug feat-scores sdk-python
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
langfuse/langfuse-python#2057 ·
Los mantenedores suelen responder en 1 día
-
tests/unit/test_prompt.py fails on a fresh clone without LANGFUSE_* env varsPosiblemente ocupada @Mathoholic la tomó hace 17 días. Abiertobug feat-prompt-management sdk-python
Dificultad 2/5 1-3 horas Aptitud para principiantes 80/100
langfuse/langfuse-python#1976 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
fix(serializer): handle single-string __slots__ and detect cycles in slotted objectsPosiblemente ocupada @hassiebp la tomó hace 13 días. Abiertobug sdk-python
langfuse/langfuse-python#2014 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder itemPosiblemente ocupada @nimarb la tomó hace 7 días. Abiertobug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
bug: GCS upload detection in MediaManager uses substring match on the full URLPosiblemente ocupada @hassiebp la tomó hace 28 días. Abiertobug feat-multimodal-media sdk-python
langfuse/langfuse-python#1913 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de langfuse/langfuse-python
Issues similares
-
area/profiles comp/cli P3 type/feature
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
NousResearch/hermes-agent#146372 ·
Los mantenedores suelen responder en 1 día
-
[BUG] OpenAI-compatible embedding model alias breaks embedder constructionPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Los mantenedores suelen responder en 1 día
-
[oblt-aw][autodoc] Document obs-aw-automerge contract and fix automerge doc inconsistenciesPosiblemente ocupada @github-actions la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día
-
GeoSeries scale and skew tests fail with pytest 9.2.0Posiblemente ocupada @jiayuasu la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
admission-deferred priority: medium status: ready work-class: scoped
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
melodic-software/claude-code-plugins#10887 · 4 comentarios ·
Los mantenedores suelen responder en 1 día