Bulk run has no empty item: skip sheet rows without a finished script

A Sume bulk item must name at least one of instruction, input, previous_run_id or attachments. Filter unfinished sheet rows on your side before you send.

4 min readSume
All posts

There is no empty item in a Sume bulk queue. Each item needs at least one of instruction, input, previous_run_id or attachments, and an item with none of them fails the create with 400 invalid_request and the details.index of the bad row. So filter the sheet before you send, and skip rows that have no finished script.

What the validator does

The same rule applies to a single run, where {} and {"input": {}} are both 400. In a bulk body the failure is atomic: a bad item fails the create before a queue exists, and Sume dispatches nothing. Unknown top-level fields are also rejected, and { "concurrency": 3 } without items is 400, not an empty queue.

Bulk create body rules (read 2026-10-06)
FieldRule
concurrencyRequired integer, 1 to 16
itemsRequired, 1 to 100 entries, in order
Each itemNames at least one of instruction, input, previous_run_id, attachments
Top levelUnknown fields rejected

A filter that keeps your row numbers

Skipping rows shifts positions, and items[i].index is the position in what you submitted, not your sheet row. Keep a list of the sheet rows you sent, in order, so index 4 maps back to the right line.

  • Drop rows where the script cell is blank; the live-commerce pattern in the docs does exactly this on the client side.
  • Store sheet_row inside each item's input as well, so a child receipt can be matched even if your index list is lost.
  • If more than 100 rows pass the filter, split them into several queues, each with its own Idempotency-Key.

Testing the filter

Run your filter on the real sheet and count what it drops before you queue. If 100 rows become 83 items, you want to know which 17 were skipped and why, and you want that list in your log, not only in your head.

Then send a pilot of three finished rows first. A pilot shows the receipt shape, the child spend and the wall time, and a bad row there costs a few dollars of generation instead of a full batch.

Remember that a queue completed status does not mean every item succeeded. Failures are recorded per item with run_id and error. Your row map is what lets you turn a failed index back into a sheet line and retry only that row.

Tradeoff

Rejecting the whole create is blunt, but it keeps a half-valid sheet from spending money. The cost is that you need a validation step. Running that step takes less time than a failed create at the end of a long data pull.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume