Merge pull request #34067 from MUSE-CODE-SPACE/fix/batch-logging-null-output-file

fix(batches): don't crash logging when a completed batch has no output file
This commit is contained in:
Mateo Wang 2026-08-17 10:01:02 -07:00 committed by GitHub
commit 2bc87ec3cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 0 deletions

View file

@ -59,6 +59,17 @@ async def _handle_completed_batch(
model_name: Optional model name
litellm_params: Optional litellm parameters containing credentials (api_key, api_base, etc.)
"""
# A completed batch whose request lines all failed has no output file - the
# results are written to a separate error_file_id and output_file_id is None.
# There is nothing to price or measure, so report an empty result set instead
# of calling _fetch_batch_output_file_content, which raises on a missing
# output file. Without this guard the logging worker crashes on every
# aretrieve_batch poll and the completed batch's zero-cost accounting is lost.
# The generic retrieval helper keeps raising for callers that explicitly ask
# for a missing output file.
if batch.output_file_id is None:
return 0.0, Usage(prompt_tokens=0, completion_tokens=0, total_tokens=0), []
file_content = await _fetch_batch_output_file_content(batch, custom_llm_provider, litellm_params=litellm_params)
if (

View file

@ -977,6 +977,27 @@ async def test_handle_completed_batch_orchestration(monkeypatch):
assert models == ["gpt-4o"]
@pytest.mark.asyncio
async def test_handle_completed_batch_no_output_file_is_zero(monkeypatch):
"""
Regression: an all-error batch completes with output_file_id=None (results go
to a separate error_file_id). _handle_completed_batch must report an empty
result set - zero cost, zero usage, no models - instead of letting the file
fetch raise "Output file id is None" on every aretrieve_batch logging poll.
"""
# The output-file fetch must not even be attempted when there is no output file.
async def _must_not_fetch(*args, **kwargs):
pytest.fail("_fetch_batch_output_file_content should not be called")
monkeypatch.setattr(bu, "_fetch_batch_output_file_content", _must_not_fetch)
cost, usage, models = await bu._handle_completed_batch(_batch(None), custom_llm_provider="openai")
assert cost == 0.0
assert (usage.prompt_tokens, usage.completion_tokens, usage.total_tokens) == (0, 0, 0)
assert models == []
@pytest.mark.asyncio
async def test_handle_completed_batch_vertex_disable_transform_path(monkeypatch):
raw_rows = [{"response": {"usageMetadata": {"promptTokenCount": 1, "candidatesTokenCount": 2}}}]