diff --git a/litellm/batches/batch_utils.py b/litellm/batches/batch_utils.py index fc2a2da44e7..c94034ea7dd 100644 --- a/litellm/batches/batch_utils.py +++ b/litellm/batches/batch_utils.py @@ -55,7 +55,7 @@ async def _handle_completed_batch( litellm_params: Optional litellm parameters containing credentials (api_key, api_base, etc.) """ # All-error batches can complete with output_file_id=None and only an error_file_id. - if batch.output_file_id is None: + if batch.output_file_id is None and getattr(batch, "error_file_id", None) is not None: return 0.0, Usage(), [] # Get batch results diff --git a/tests/test_litellm/batches/test_batch_utils.py b/tests/test_litellm/batches/test_batch_utils.py index 77e57a38aa5..febeedebe5f 100644 --- a/tests/test_litellm/batches/test_batch_utils.py +++ b/tests/test_litellm/batches/test_batch_utils.py @@ -600,7 +600,7 @@ async def test_calculate_batch_cost_and_usage_orchestration(monkeypatch): # =========================================================================== # -def _batch(output_file_id): +def _batch(output_file_id, error_file_id=None): from litellm.types.llms.openai import Batch return Batch( @@ -612,6 +612,7 @@ def _batch(output_file_id): object="batch", status="completed", output_file_id=output_file_id, + error_file_id=error_file_id, ) @@ -720,7 +721,10 @@ async def test_handle_completed_batch_all_error_batch_no_output_file(monkeypatch monkeypatch.setattr(bu, "_get_batch_output_file_content_as_dictionary", fake_get_content) - cost, usage, models = await bu._handle_completed_batch(_batch(None), custom_llm_provider="openai") + cost, usage, models = await bu._handle_completed_batch( + _batch(None, error_file_id="file-err"), + custom_llm_provider="openai", + ) assert cost == 0.0 assert usage.total_tokens == 0 @@ -730,6 +734,13 @@ async def test_handle_completed_batch_all_error_batch_no_output_file(monkeypatch assert called is False +@pytest.mark.asyncio +async def test_handle_completed_batch_missing_output_without_error_file_still_raises(): + """Completed batches with no output and no error file keep the explicit fetch error.""" + with pytest.raises(ValueError, match="Output file id is None"): + await bu._handle_completed_batch(_batch(None), custom_llm_provider="openai") + + # =========================================================================== # # Remaining branch: vertex usage disable-transform path. #