One Bad Row Killed the Whole Batch: Partial-Failure Handling for n8n Loops A developer running LLM workflows in n8n described how a single malformed lead record halted a nightly batch, leaving 453 valid leads unprocessed until a client noticed the gap. The fix, the developer writes, is to isolate per-item failures inside sub-workflows or error-handling branches, route failed items to a dead-letter list keyed by business ID, report processed/failed/skipped/retried counts separately, and retry only from the dead-letter list to avoid duplicating good records. This is part of my build-in-public series on running LLM workflows in n8n in production. Everything here is from real templates I sell and support — the mistakes are mine, the fixes are tested. A nightly workflow of mine processed a batch of new leads: enrich each one, score it, write it to the CRM. One night a single lead had a malformed phone field, the enrichment node threw, and the execution stopped. The other 453 leads sat unprocessed until the next morning, when a client asked why half the day's leads were missing. Nothing about this was exotic. A batch loop that stops on the first error is the default behavior in most workflow tools, and it turns one bad record into a silent outage for every record behind it. The error itself was visible — the execution log showed the failure. What was invisible was the cost: hundreds of good records that never got processed because they happened to queue behind a bad one. The fix is not "validate better." You will never validate away every malformed record from a source you do not control. The fix is to decide, per item, what failure means — and to make that decision before the loop runs, not after it stops. First, isolate failures to the item that caused them. In n8n this means the per-item work runs where an error cannot kill the loop: a sub-workflow executed per item, or an error-handling branch that catches the failure and returns it as data instead of throwing. The loop itself never sees an exception — it sees a result, either success or a structured failure record. Once a bad row produces a row in a failure list instead of a stopped execution, the batch always completes, and "complete" stops being a lie. Second, collect failures into a dead-letter list, not a log line. A failed item goes into a table with the item's business key, the error, and the raw payload — everything needed to reprocess it without re-running the whole batch. My rule: a batch that ends with failures still reports success for the good items and a separate count for the failed ones, and the failed list is the input to a retry workflow, not a note for someone to read someday. If a failure cannot be retried from the list alone, the list is missing a field, and that is the bug to fix. Third, report four numbers, not one status. Processed, failed, skipped as duplicates, and retried. When failed jumps from zero to one, that is a data problem worth one look. When failed jumps to forty, that is a schema change upstream, and I want to know before the client does. A batch that reports only "done" hides exactly the distinction between "everything worked" and "everything after row 47 never ran" — which is the distinction the whole report exists to make. Retrying the whole batch is how a partial failure becomes a duplicate problem: the good items run twice. So retries run against the dead-letter list only, keyed by the business id, with the same dedupe check the main loop uses. A retried item that succeeds is marked done; one that fails again stays on the list with its new error. Nothing ever re-enters the main batch, and the main batch never re-processes a good item because a bad one showed up late. The principle is simple: a batch loop's job is to finish the batch, not to stop at the first surprise. One bad row should cost you one row, one entry in a list, and one retry — never the 453 good rows standing behind it. I'm building AI Automation Lab https://payhip.com/haopengailab — production-ready n8n workflow templates. The free AI Hook Generator https://payhip.com/b/ulER8 shows how I structure real workflows; my open-source templates live at github.com/zhp910318/n8n-ai-automation-lab https://github.com/zhp910318/n8n-ai-automation-lab .