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
- スター
- 498
- フォーク
- 361
- 平均マージ
- 16時間 40分
- マージ済み PR(30日)
- 38
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
langfuse/langfuse-python のほかの issue
-
bug feat-prompt-management sdk-python
難易度 2/5 1〜3時間 初心者へのやさしさ 80/100
langfuse/langfuse-python#1976 ·
メンテナーはふだん 1 日以内に返信
-
bug: ChatPromptClient.compile appends str(whole list) once per non-dict placeholder item対応中かも @hassiebp が 2 日前に担当しました。 オープンbug feat-prompt-management sdk-python
langfuse/langfuse-python#1971 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
bug: LANGFUSE_MAX_EVENT_SIZE_BYTES is parsed but never enforced for score events対応中かも @hassiebp が 2 日前に担当しました。 オープンbug feat-scores sdk-python
langfuse/langfuse-python#1966 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
bug: Partial-failure (207) ingestion response retries the whole batch up to 3x; per-item error details only logged at DEBUG対応中かも @hassiebp が 2 日前に担当しました。 オープンbug feat-ingestion
langfuse/langfuse-python#1965 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
bug: GCS upload detection in MediaManager uses substring match on the full URL対応中かも @hassiebp が 11 日前に担当しました。 オープンbug feat-multimodal-media sdk-python
langfuse/langfuse-python#1913 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
langfuse/langfuse-python の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 83/100
PedestrianDynamics/pyFDS-Evac#766 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1〜3時間 初心者へのやさしさ 91/100
alchaincyf/nuwa-skill#86 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 2 日以内に返信
-
Docs Needs Triage
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
pandas-dev/pandas#71055 ·
メンテナーはふだん 1 日以内に返信
-
[Bug]: graphify reads files that git's global ignore file hides対応中かも @smngvlkz が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
Graphify-Labs/graphify#4335 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信