bug(langchain): failed streaming LLM runs retain IDs in callback memo
I maintainer di solito rispondono entro 1 giorno
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Bug description
LangchainCallbackHandler retains completed LLM run IDs in _updated_completion_start_time_memo when a streaming execution terminates with an error.
The successful completion path (on_llm_end) removes the run ID from the set, but the error path (on_llm_error) does not perform the same cleanup.
As a result, long-lived callback handlers reused across failed streaming executions can accumulate stale UUID entries.
Root cause
In langfuse/langchain/CallbackHandler.py:
on_llm_new_token()records the first-token timestamp and adds therun_idto_updated_completion_start_time_memo.on_llm_end()removes therun_idin itsfinallyblock.on_llm_error()ends the observation but does not remove therun_idfrom the memo._detach_observation()and_reset()do not clear this set.
Steps to reproduce
Using a LangchainCallbackHandler with an in-memory Langfuse test client:
- Start an LLM run using
on_llm_start(). - Simulate the first streamed token using
on_llm_new_token(). - Confirm the run ID exists in
_updated_completion_start_time_memo. - Terminate the run using
on_llm_error(RuntimeError("synthetic failure"), run_id=run_id). - Inspect
_updated_completion_start_time_memo.
Actual behavior: The failed run ID remains in the set after the observation has ended.
Expected behavior: The failed run ID should be removed, while unrelated active run IDs remain untouched.
Impact
This causes incremental retention of UUID identifiers when streaming LLM executions fail and the same callback handler is reused.
The observed retention is limited to UUID entries. There is no evidence of retained generations, spans, or a significant process-level memory leak.
Proposed solution
Ensure on_llm_error() discards its own run_id from _updated_completion_start_time_memo in a finally block, mirroring the existing cleanup in on_llm_end().
This should preserve:
- Active nested or concurrent run state.
- Existing OpenTelemetry context handling.
- LangGraph control-flow and resume behavior.
- Current public SDK behavior.
Validation
I reproduced this issue locally using Langfuse Python SDK 4.17.0 and created a deterministic regression test.
Before the fix (RED):
- The failed run ID remained in the memo.
- The regression assertion failed as expected.
After the minimal fix (GREEN):
- The failed run ID was removed.
- Another active run ID remained unaffected.
- All 24 tests in
tests/unit/test_langchain.pypassed. - Targeted Ruff lint and formatting checks passed.
git diff --checkpassed.
Full unit suite on Windows:
- 883 passed
- 2 skipped
- 3 failed in unrelated tests (two subprocess import failures and one platform-dependent path serialization assertion).
The full suite has not yet been confirmed green on Linux.
Contribution
I have a minimal fix and regression test ready locally.
I'm happy to open a focused PR if the maintainers agree with the proposed approach.
- Lingua principale
- Python
- Stelle
- 498
- Fork
- 361
- Merge medio
- 16h 40m
- PR unite (30g)
- 38
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di langfuse/langfuse-python
-
tests/unit/test_prompt.py fails on a fresh clone without LANGFUSE_* env varsForse già presa @Mathoholic l’ha presa 1 giorno fa. Apertabug feat-prompt-management sdk-python
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
langfuse/langfuse-python#1976 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder itemForse già presa @hassiebp l’ha presa 3 giorni fa. Apertabug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
bug: LANGFUSE_MAX_EVENT_SIZE_BYTES is parsed but never enforced for score eventsForse già presa @hassiebp l’ha presa 3 giorni fa. Apertabug feat-scores sdk-python
langfuse/langfuse-python#1966 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
bug: non-numeric status in a 207 error entry raises inside handle_exception, kills the score consumer thread, flush()/shutdown() then hangForse già presa @hassiebp l’ha presa 3 giorni fa. Aperta[Integrations] Language Clients bug feat-scores sdk-python
langfuse/langfuse-python#1967 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
bug: Partial-failure (207) ingestion response retries the whole batch up to 3x; per-item error details only logged at DEBUGForse già presa @hassiebp l’ha presa 3 giorni fa. Apertabug feat-ingestion
langfuse/langfuse-python#1965 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di langfuse/langfuse-python
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
KalicoCrew/kalico#1012 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 82/100
esphome/esphome.io#7657 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
VNG-Realisatie/gemma-zaken#2658 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
comp/gateway comp/plugins duplicate P3 type/bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
NousResearch/hermes-agent#137019 ·
I maintainer di solito rispondono entro 1 giorno