Validate before you run
The question for this lesson: you’ve edited a 200-line pipeline. Before you run it over a million rows, how do you check it’s correct, without waiting for the whole run?
What you’ll be able to do
Section titled “What you’ll be able to do”- Use
--dry-runto validate config structure and declared types without processing data, and know what it leaves for the real run. - Use
--explainto print the execution plan and read it. - Decode a diagnostic E-code with
explain --code.
Check without running: --dry-run
Section titled “Check without running: --dry-run”clinker run customer_etl.yaml --dry-run--dry-run parses your YAML, checks the config’s structure, validates your declared schema
types, and resolves the output paths, then stops, without reading a single data row. If a
required field is missing or a schema type doesn’t exist, you find out in a second.
Be honest about its reach, though: --dry-run validates the structure and declared types
before reading data. Deeper logic errors (a dangling input: that names a node which isn’t
there, an unknown field or method inside a CXL expression) aren’t caught here. Those surface
when you actually run, because they depend on the data flowing through. So treat --dry-run as
the fast first gate, not a full proof of correctness.
🌱 New here? — why it's instant
Validation doesn’t touch your data. Clinker checks the shape of the job (the config
structure, the declared schema types, the resolved outputs), which is fast no matter how big
the file is. Only a real run reads rows. So --dry-run costs the same whether your file has 10
rows or 10 million.
You can also process just the first few rows to sanity-check output: --dry-run -n 5 runs 5
records to stdout instead of the output file.
See the shape: --explain
Section titled “See the shape: --explain”clinker run customer_etl.yaml --explain--explain prints the execution plan in labelled sections (the CXL it compiled, the node
graph, and how data flows), so you can confirm the pipeline does what you think before you run
it. The full output is long; here are the three sections you’ll read most (trimmed):
=== Execution Plan ===
Mode: StreamingTransforms: 1Output projections: 1DAG nodes: 3
=== CXL Expressions ===
Transform 'tagged': emit is_active = status == "active"
=== DAG Topology ===
● [source] customers │ [transform] tagged │ [output] resultsDecode a diagnostic: explain --code
Section titled “Decode a diagnostic: explain --code”When a run or dry-run fails, it prints an E-code. You don’t have to guess what it means; look any code up directly, with no config needed:
clinker explain --code E105That prints a full explanation of the diagnostic: what it means, an example that triggers it,
and how to fix it. E105, for instance, is “Channel binding references undeclared config
key”: a channel file bound a config key the target pipeline never declared. The point isn’t to
memorize codes. Whenever a run prints one, explain --code turns it into a plain
explanation on the spot.
Use: validate a pipeline
Section titled “Use: validate a pipeline”Run --dry-run on this one. Predict whether it passes, then check.
> output appears here — predict, then run
Modify: break it on purpose
Section titled “Modify: break it on purpose”Now make --dry-run fail, and find the one break it lets through. In the runner above, try
two changes, one at a time, and predict the outcome of each before you re-run.
// quick check
What does `--dry-run` validate before reading any data?
--dry-run validates the config's structure and declared types and resolves outputs, without reading data, so it's instant regardless of file size. Deeper logic errors (a dangling input:, an unknown CXL field or method) aren't caught here; they surface when you run.
Create: pre-flight a pipeline you build
Section titled “Create: pre-flight a pipeline you build”Now put the tools together on a pipeline of your own. Author a small one from scratch: a csv
source with a declared schema, one transform that emits a computed field, and an output.
Then run the full pre-flight before any real run:
clinker run mine.yaml --dry-run: does the config compile, and do the declared types check out?clinker run mine.yaml --explain: does=== DAG Topology ===show the nodes wired the way you intended, and does=== CXL Expressions ===show the formula you meant?- Fix anything it surfaces, then run for real.
Predict, before you run: if you misspell a transform’s input:, which step catches it? Not
--dry-run. A dangling input: is a wiring error, not a declared-type error, so it passes
dry-run. Reading the --explain topology is what catches it before you waste a full run.