Dry-run mode
Preview a pipeline without touching the output destination.
cannectors run --dry-run <pipeline.yaml> runs everything up to (but
not including) the output's side effects. It's the safest way to
validate a fresh pipeline against a real source before you let it
write to production.
What dry-run does
- Validates the YAML against the JSON Schema. Same as
cannectors validate. - Resolves env vars the same way a normal run does.
- Executes the input — for real. The source API gets hit, the database query runs, the webhook listener starts.
- Runs every filter — for real. HTTP enrichments, SQL enrichments, script transforms all execute against real services.
- Prepares the output — formats the records as they would be sent, serializes them, etc.
- Prints a preview — the prepared payloads are printed to stdout instead of being sent to the destination.
Steps 3 and 4 are unchanged from a real run. Only the output side effect is suppressed.
Why steps 3–4 still run
A pipeline isn't just YAML — it depends on the actual data shape coming out of the source. Real-running the input and filters is the only way to surface "this field is missing", "the API returns 401", "the condition expression doesn't compile against this record".
If you don't want the source API hit either, point the pipeline at a fixture or a local mock. The test lab exists for exactly this case.
Tuning the preview
The optional top-level dryRunOptions block controls what gets
printed:
dryRunOptions:
previewLimit: 5 # max number of preview entries to print
includeHeaders: true # include the request headers in the preview
includeBody: true # include the request body in the previewDefault is previewLimit: 10, both inclusions on. Lower the limit when
the source returns large batches and you only need a sanity check.
Sample output
$ cannectors run --dry-run sync-orders.yaml
· loading pipeline sync-orders v1.0.0
✓ validated 1 input · 3 filters · 1 output
· httpPolling GET https://source.example.com/api/orders
· fetched 48 records
· mapping 48 → 48
· condition 37 kept · 11 skipped
· dry-run output preview (first 5 of 37):
POST https://destination.example.com/api/orders/import
Content-Type: application/json
Authorization: Bearer ******
[
{"id": "ord_001", "email": "alice@example.com", "amount": 42.00},
{"id": "ord_002", "email": "bob@example.com", "amount": 19.50},
…
]
✓ dry-run complete — 0 destination writesThe body is the actual JSON that would be POSTed. Auth headers are redacted.
When NOT to use dry-run
Dry-run isn't a substitute for testing. The input and filters all run for real, which means:
- The source API sees a real request (and may rate-limit you).
http_callenrichments are billed/quota-consumed.scriptfilters run and can mutate external state if you've written them to.
For deterministic testing, use the local test lab which spins up WireMock + PostgreSQL containers.