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
t2-etl-quarantine.nika.yaml
How it works
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.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.Constructs you just used
| Construct | Where | Reference |
|---|---|---|
on_error: recover: | rows | Error model |
nika:validate gate | check | Builtins |
when: branch routing | good · quarantine | Workflows |
| jq aggregation | good | Builtins |
Make it yours
- Add a
nika:notifytask 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.