Skip to main content
T2 chain · data engineering: the on_error: recover: example. The difference between « re-run the whole night » and « fix three rows tomorrow morning » is one block: bad data is data, not an exception.

The job

The nightly batch dies at row 14,203 and the whole pipeline dies with it. Here the malformed-CSV case recovers to an empty batch, the schema gate splits good from bad, rejects land in a quarantine file with their validation errors, and the good rows aggregate per currency, in jq, deterministically.

The shape

The file

etl-quarantine.nika.yaml

How it works

1

recover: is the safety net

on_error: recover: ${{ tasks.empty_batch.output }}: when the CSV won’t parse, the task yields the fallback instead of failing. Downstream sees an empty batch, not a dead pipeline.
2

The gate splits, when: routes

nika:validate returns {valid, errors} · two when: branches route the run: good rows aggregate, bad batches quarantine WITH their error report.
3

jq does the accounting

group_by(.currency) + add: totals are arithmetic, not model output. No LLM call anywhere in this workflow.

Constructs you just used

Make it yours

  • Add a nika:notify task on the quarantine branch: data-quality alerts only when something was actually rejected.
  • Chain Release notes’ pattern to post the daily totals to your team channel.
  • Validate against your real row schema: the gate is just JSON Schema.

Next · Release radar

The feed-mode example: RSS/Atom parsed natively, diffed against last run’s state.