## TL;DR

InvalidBatch means you tried to add data to a batch (or job) that is no longer open, most often because the job was closed or the batch already finished. Check the job and batch states first, then create a new job and add the data there instead of retrying against the dead one.

## Error

```text
batchInfo
  state = InvalidBatch
  stateMessage = Batch is in an invalid state for this operation
```

## Steps

1. GET the job status and then the batch status. Expected: you see the batch in Completed, Failed, or the job in Closed or Aborted.
2. Do not retry the same batch. Create a new job for the same object and operation. Expected: the new job returns state Open.
3. Add the batch data to the new job and close the job when all batches are added. Expected: batches move from Queued to InProgress.
4. Poll the batch state until it reaches Completed, then GET the results. Expected: you get success and error result files.
5. If InvalidBatch appears immediately on a fresh job, check the Content-Type header and CSV shape; malformed payloads can also land here. Expected: fixing the payload clears it.

## When to use

- Bulk API 1.0 returns InvalidBatch on add-batch or close-job calls.
- A long-running agent job tries to reuse a job handle from hours earlier.
- Retries of a failed load keep failing with the same state error.

## When not to use

- Bulk API 2.0 (uses ingest jobs with a different state model).
- Batch failures with row-level errors (those are in the result file, not the batch state).

## Tool compatibility

- Salesforce Bulk API 1.0 (async API) on any object.
- ETL tools and agents that hold job handles across long runs.

## Variant phrasings

### Batch is in an invalid state for this operation

The long form; check job and batch state before retrying.

### InvalidBatch on close job

The job was already closed or aborted; create a new job.

## Why it happens

Batches are state machines: Queued, InProgress, Completed, Failed. Operations are only valid in certain states, and jobs expire. A stale handle from a timed-out agent run points at a batch that has already left the valid states.

## Edge cases

- Jobs left open too long get cleaned up by Salesforce; always close jobs promptly after adding batches.
- Adding a batch to a job in Aborted state returns InvalidBatch; check the job state, not just the batch.
- Parallel agents sharing one job handle race on close; give each worker its own job.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_B0f1d-Rhs1CVenahyrBzYQ
