# OpenAI Batch expired: unfinished requests, still billed for the finished ones

## The symptom

`batches.retrieve` shows status `expired`: the batch did not complete within the 24-hour completion window. Some requests may have completed; the rest did not.

## Confirm the cause

1. **Read `request_counts`.** It breaks down total, completed, and failed. Completed requests inside an expired batch are still billed and their results are still in the output file.
2. **Check the error file.** Unfinished requests get `error.code: "batch_expired"` on their error lines. Join to your inputs via `custom_id` to list exactly which ones never ran.
3. **Ask why it expired.** Usual reasons: the batch was too large for the queue, it was submitted during a busy period, or many requests were slow (long outputs, heavy models).

## The fix

- Download the output file first and keep every completed result. You already paid for them.
- Build a retry input file with only the `custom_id`s that expired or failed. Submit it as a new batch, ideally smaller or at an off-peak time.
- For huge workloads, split into several smaller batches up front so one slow batch cannot strand the rest.

## Verify the fix

After the retry, every original `custom_id` has exactly one successful output line across the two batches, and no `custom_id` was paid for twice. Track batch age while polling; alert if a batch sits in progress past 20 hours so expiry never surprises you.