bug: non-numeric status in a 207 error entry raises inside handle_exception, kills the score consumer thread, flush()/shutdown() then hang
維護者通常 1 天內回覆
評估
這個 Issue 還沒有評估資料。
描述
Describe the bug
ScoreIngestionConsumer.upload() calls handle_exception(e) from inside its except block (score_ingestion_consumer.py#L141-L153). generate_error_message does int(error.status) on string statuses with no guard (parse_error.py#L75-L99), so a non-numeric status such as "n/a" raises ValueError from inside the error handler.
Nothing catches it in upload() or in run() (L129-L139), so the daemon consumer thread exits, and nothing restarts it (only the fork re-init does). The batch that triggered the error is still acknowledged by the finally block, but every later score event stays in the queue, unfinished_tasks never reaches 0, and Langfuse.flush() / shutdown() block forever on Queue.join() (resource_manager.py#L629-L640, no timeout).
Likelihood: the trigger needs a 207 response whose errors[].status is non-numeric. The Langfuse server does not send that today, so this is a defensive-hardening bug (a misbehaving proxy/gateway or a future server change would trigger it). The consequence is silent loss of later scores plus an unbounded hang at exit, and the fix is small.
Steps to reproduce
Uses httpx.MockTransport, no server needed:
import httpx, threading
from queue import Queue
from langfuse._utils.request import LangfuseClient
from langfuse._task_manager.score_ingestion_consumer import ScoreIngestionConsumer
import time; time.sleep = lambda s: None
def h(req): return httpx.Response(207, json={"errors": [{"status": "n/a", "message": "m"}]})
cl = LangfuseClient("pk", "sk", "http://x", "1", 5, httpx.Client(transport=httpx.MockTransport(h)))
q = Queue(); c = ScoreIngestionConsumer(ingestion_queue=q, identifier=0, client=cl, public_key="pk", flush_at=1, flush_interval=0.2)
c.start(); q.put({"id": "a", "type": "t", "body": {}}); c.join(3)
print("consumer alive:", c.is_alive())
q.put({"id": "b", "type": "t", "body": {}})
t = threading.Thread(target=q.join, daemon=True); t.start(); t.join(3); print("flush hung:", t.is_alive())
Observed output (traceback goes to stderr):
File ".../langfuse/_utils/parse_error.py", line 86, in generate_error_message
int(error.status) if isinstance(error.status, str) else error.status,
ValueError: invalid literal for int() with base 10: 'n/a'
consumer alive: False
flush hung: True
Direct check: handle_exception(APIErrors([APIError("abc", "m")])) raises ValueError: invalid literal for int() with base 10: 'abc' (a None status is fine).
Langfuse Cloud or self-hosted?
Not server dependent (reproduced with a mock transport).
If self-hosted, what version are you running?
n/a
SDK and integration versions
langfuse 4.17.0 (main @ bf11ec121479145923ff27b32ec2ad1d06fd2d51), Python 3.14.0.
Additional information
Possible direction: convert statuses with a safe helper (try: int(s) except (TypeError, ValueError): None) in parse_error.py; make handle_exception never raise (fall back to logger.error); and wrap the loop body of ScoreIngestionConsumer.run() in try/except Exception that logs and continues so a single bad batch cannot end the thread. A bounded join() in flush() would be related hardening.
Related, different root cause: #1799 (shutdown() hangs on _score_ingestion_queue.join() after a cached resource manager is reused). Both end with consumers that are gone and an unbounded join().
Are you interested in contributing a fix for this bug?
Yes
- 主要語言
- Python
- 星號
- 502
- 分支
- 381
- 平均合併
- 18 小時 44 分鐘
- 30 天內合併 PR
- 61
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
langfuse/langfuse-python 的其他 Issue
-
tests/unit/test_prompt.py fails on a fresh clone without LANGFUSE_* env vars可能已有人在做 @Mathoholic 於 14 天前認領。 未關閉bug feat-prompt-management sdk-python
難度 2/5 1-3 小時 新手友好度 80/100
langfuse/langfuse-python#1976 · 3 則留言 ·
維護者通常 1 天內回覆
-
bug(openai): a stream that fails mid-iteration ends the generation without level ERROR可能已有人在做 @hassiebp 於 3 天前認領。 未關閉bug integration-openai sdk-python
langfuse/langfuse-python#2039 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
fix(serializer): handle single-string __slots__ and detect cycles in slotted objects可能已有人在做 @hassiebp 於 9 天前認領。 未關閉bug sdk-python
langfuse/langfuse-python#2014 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder item可能已有人在做 @nimarb 於 4 天前認領。 未關閉bug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
bug: GCS upload detection in MediaManager uses substring match on the full URL可能已有人在做 @hassiebp 於 24 天前認領。 未關閉bug feat-multimodal-media sdk-python
langfuse/langfuse-python#1913 · 1 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
查看 langfuse/langfuse-python 的全部 Issue
相似的 Issue
-
難度 1/5 1 小時以內 新手友好度 72/100
slavakurilyak/awesome-ai-agents#845 ·
維護者通常 1 天內回覆
-
tests: pin that the atomic writers in utils/paths.py stage the temporary file in the target's directory可能已有人在做 @SauravMukherjee44 今天認領。 未關閉claimed difficulty:2 enhancement good first issue
難度 1/5 1-3 小時 新手友好度 92/100
MakazhanAlpamys/Soup#2178 · 2 則留言 ·
維護者通常 1 天內回覆
-
[BUG] dcg.waggr permutation p-values are folded twice, so near-zero scores get the smallest p-values未關閉
難度 2/5 1-3 小時 新手友好度 75/100
scverse/rapids-singlecell#854 ·
維護者通常 1 天內回覆
-
Slang input: int8_t4_packed and uint8_t4_packed are copied into CrossGL可能已有人在做 @ninglinLiu 於 1 天前認領。 未關閉area:frontend backend:slang bug direction:input
難度 2/5 1-3 小時 新手友好度 70/100
CrossGL/crosstl#2801 · 1 則留言 ·
維護者通常 1 天內回覆
-
random_elements(unique=True) on an OrderedDict: ZeroDivisionError once only zero weights remain, AssertionError with use_weighting=False可能已有人在做 @ekanshul 今天認領。 未關閉
難度 2/5 1-3 小時 新手友好度 85/100
維護者通常 13 天內回覆