dbt test flakiness: passes on rerun with zero changes
Diagnoses dbt test flakiness where the same test passes on rerun with zero code or data changes. Use when a test flips between pass and fail across identical runs. Not for tests that fail consistently on real bad data.
TL;DR
A test that passes on an unchanged rerun is racing something: concurrent loads mutating the table mid-test, non-deterministic SQL (row limits without order, current timestamp boundaries), or warehouse eventual consistency. Capture the failing rows at failure time with store_failures, then pin down which input moved. Flaky tests erode trust until the race is named.
dbt test flakiness: passes on rerun with zero changesUse this when
- dbt test fails, then passes on immediate rerun with no changes
- failures cluster at specific times (during loads, top of the hour)
- the test involves timestamps, limits, sampling, or tables loaded concurrently with the test run
Not for this skill when
- the test fails every run until data is fixed, that is a real failure, not flakiness
- the model itself is non-deterministic, fix model determinism first
- failures correlate with code deploys, treat as regression, not flake
Steps
Turn on store_failures for the suspect test (or keep the failures table from the last red run) and rerun until it fails once. Save the failing rows and the run timestamps. Verify: you have a captured set of failing rows from a real failure.
Check whether those rows or their upstream tables were being written at the failure time: look at load job schedules, warehouse query history, and whether the failing rows exist in their failed form now. Verify: you know whether the data changed between fail and pass, or stayed identical.
If data was identical, audit the test SQL for non-determinism: limit without order by, comparisons against now or current_date at boundaries, floating point equality, or sampling. Rewrite the test to be deterministic (ordered limits, date truncation, tolerance for floats). Verify: the test query is deterministic for a fixed input.
If data moved, fix the race at the orchestration level: run tests after loads complete (build order or job dependencies), not in parallel with the load of the tested table. Rerun the full sequence three times. Verify: three consecutive full runs give the same test result.
Variant phrasings
flaky only in CI
CI runs tests against shared or freshly loaded schemas with more concurrency. Reproduce the CI ordering and overlap locally or in a staging job before declaring it fixed.
flaky unique or relationships test
Both read two tables that may load at different times. Testing after both loads, or testing within one build that orders them, removes the cross-table race.
Compatibility: dbt-core generic and singular tests with store_failures (dbt 1.3 and later test configs). Orchestration fixes apply in dbt Cloud jobs or Airflow-style schedulers.
Why it happens
Tests are queries over a moving system. If the table (or its join partner) changes between the failing run and the rerun, both results are correct for their moment. Non-deterministic test SQL creates the same flip with completely static data. Until you capture the failing rows and the clock, flake reports are guesses.
Edge cases / pitfalls
- Deleting or loosening a flaky test without naming the race hides real failures later; require a root cause note.
- Retries in CI convert flake into latency and mask frequency; track failure rate even when retries pass.
- Boundary tests on timestamps flake at midnight and month end on schedule; treat calendar-correlated flakes as deterministic bugs.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_ruvtzcwrtn8xUCCG-SJvsQ