fix(check_batch_cost): mark completed all-failed batches as processed - #34785
fix(check_batch_cost): mark completed all-failed batches as processed#34785devin-ai-integration[bot] wants to merge 1 commit into
Conversation
…processed An OpenAI batch where every request fails completes with status=completed but output_file_id=None. It matched neither the completed-with-output nor the failed/expired/cancelled branch, so batch_processed never flipped and the row was re-polled forever, saturating the oldest-N poll window and starving newer batches. Mark such batches complete + batch_processed=True (no cost to track). Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Greptile SummaryThis PR prevents completed all-failed batches from remaining in the polling queue.
Confidence Score: 5/5The PR appears safe to merge, with the new terminal case aligned with existing persistence and polling conventions. Completed batches without output files are now marked processed, while batches with output files retain the existing cost-tracking path and legacy-schema polling continues to exclude the persisted complete status.
|
| Filename | Overview |
|---|---|
| enterprise/litellm_enterprise/proxy/common_utils/check_batch_cost.py | Extends terminal batch handling to completed responses without output files, consistently using the existing completed-to-complete status mapping. |
| tests/proxy_unit_tests/test_check_batch_cost.py | Adds focused regression coverage for persisting and retiring an all-failed completed batch without attempting output-file retrieval. |
Reviews (1): Last reviewed commit: "fix(check_batch_cost): mark completed ba..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
TLDR
Problem this solves:
How it solves it:
status=completedwithoutput_file_id=Noneas terminalcomplete+batch_processed=Trueso polling stopsRelevant issues
Linear ticket
Resolves LIT-4826
Pre-Submission checklist
Screenshots / Proof of Fix
Root cause. In
CheckBatchCost.check_batch_costthe loop had only two terminal branches:When every request in a batch fails, OpenAI reports
status=completedwithoutput_file_id=None(only anerror_file_id). That matches neither branch, sobatch_processednever flips to true. The row is re-polled every cycle, and because the poll query istake=MAX_OBJECTS_PER_POLL_CYCLEorderedcreated_at ASC, accumulating poison rows permanently occupy the oldest-N window and starve newer batches. The stale-cleanup pass does not rescue them either, since it excludescompleted.Fix. The
completed-with-no-output_file_idcase now falls into the terminal branch and is written back ascomplete+batch_processed=Truewith no cost tracking (no rows succeeded, so there is no usage to cost). Partially-failed batches still carry an output file and go through the existing cost-tracking branch unchanged.Live proof (commit
a7f416c4f1) against a source proxy on localhost:4000 (PROXY_BATCH_POLLING_INTERVAL=30) hitting real OpenAI with a managed batch whose every row is invalid (temperatureout of range), so OpenAI completes it with only failed rows and no output file.Upload the managed file and create the batch:
Once OpenAI finished, the batch is completed with no output file and two failed rows:
With the fix, the poller retires the row instead of re-polling it forever:
batch_processed=ton a completed batch with a nulloutput_file_idis only reachable through the new branch. On the pre-fix source the row staysbatch_processed=fand is re-selected every cycle.A regression test pins this:
tests/proxy_unit_tests/test_check_batch_cost.py::TestCheckBatchCost::test_completed_with_no_output_file_marks_job_processeddrives a completed response withoutput_file_id=Nonethrough the realcheck_batch_costloop and asserts the row is markedcomplete+batch_processed=Trueand that no output file is fetched. It fails on the pre-fix source and passes after.Type
🐛 Bug Fix
Changes
enterprise/litellm_enterprise/proxy/common_utils/check_batch_cost.py: the terminal branch now also handlesstatus=completedwithoutput_file_id=None, writingstatus=complete+batch_processed=True.tests/proxy_unit_tests/test_check_batch_cost.py: added a regression test for the all-failed completed batch.Link to Devin session: https://app.devin.ai/sessions/31841d4336cd405c8a5b57fb9611dc77