Downstream models still get built even when relationships test fails in dbt build

The problem I’m having

According to the official docs, when a test on an upstream resource fails during dbt build, downstream models should be skipped (“Skipping on failures”).
However, after creating two staging models and defining a relationships test between them (which fails), I found that the downstream model still gets built.

The context of why I’m trying to do this

  • I want relationships test failures in the staging layer to prevent downstream models (like intermediate or mart models) from being built.

What I’ve already tried

  • Reduced threads to 1 and used --fail-fast, but the downstream model still gets built.
  • Confirmed that when not_null or unique tests fail, downstream models do get skipped as expected.
  • From the logs:
    • When only a relationships test exists, the downstream model builds before the test runs.
    • But when a not_null or unique test is also present, tests run before the downstream model.

Some example code or error messages

  • stg_comapny.sql

    SELECT 
        id,
        name
    FROM (
        SELECT * FROM UNNEST([
            STRUCT(1 AS id, 'Company A' AS name),
            STRUCT(2 AS id, 'Company B' AS name),
            STRUCT(3 AS id, 'Company C' AS name)
        ])
    ) AS t
    
  • stg_center.sql

    SELECT 
        id,
        company_id,
        name
    FROM UNNEST([
        STRUCT(101 AS id, 1 AS company_id, 'Center A1' AS name),
        STRUCT(102 AS id, 2 AS company_id, 'Center B1' AS name),
        STRUCT(103 AS id, 3 AS company_id, 'Center C1' AS name),
        STRUCT(104 AS id, 4 AS company_id, 'Center D1' AS name) -- This row has an invalid FK reference
    ])
    
  • int_center.sql

    WITH source AS (
        SELECT
            *
        FROM {{ ref('stg_center') }}
    )
    
    SELECT
        *
    FROM source
    
  • schema.yml

    models:
      - name: stg_company
    
      - name: stg_center
        columns:
          - name: company_id
            data_tests:
              - relationships:
                  to: ref('stg_company')
                  field: id
    
  • Run dbt build --select stg_center+ stg_company+

    09:07:58  Running with dbt=1.9.4
    09:07:59  Registered adapter: bigquery=1.9.1
    09:07:59  Found 25 models, 81 data tests, 19 sources, 698 macros
    09:07:59  
    09:07:59  Concurrency: 1 threads (target='local')
    09:07:59  
    09:08:01  1 of 5 START sql view model temp.stg_center .............................. [RUN]
    09:08:02  1 of 5 OK created sql view model temp.stg_center ......................... [CREATE VIEW (0 processed) in 0.74s]
    09:08:02  2 of 5 START sql view model temp.stg_company ............................. [RUN]
    09:08:02  2 of 5 OK created sql view model temp.stg_company ........................ [CREATE VIEW (0 processed) in 0.59s]
    09:08:02  3 of 5 START sql table model temp.int_center ............................. [RUN]
    09:08:04  3 of 5 OK created sql table model temp.int_center ........................ [CREATE TABLE (4.0 rows, 0 processed) in 1.77s]
    09:08:04  4 of 5 START sql table model temp.int_company ............................ [RUN]
    09:08:06  4 of 5 OK created sql table model temp.int_company ....................... [CREATE TABLE (3.0 rows, 0 processed) in 1.76s]
    09:08:06  5 of 5 START test relationships_stg_center_company_id__id__ref_stg_company_ .... [RUN]
    09:08:07  5 of 5 FAIL 1 relationships_stg_center_company_id__id__ref_stg_company_ ........ [FAIL 1 in 0.80s]
    09:08:07  
    09:08:07  Finished running 2 table models, 1 test, 2 view models in 0 hours 0 minutes and 7.45 seconds (7.45s).
    09:08:07  
    09:08:07  Completed with 1 error, 0 partial successes, and 0 warnings:
    09:08:07  
    09:08:07  Failure in test relationships_stg_center_company_id__id__ref_stg_company_ (models/staging/schema.yml)
    09:08:07    Got 1 result, configured to fail if != 0
    09:08:07  
    09:08:07    compiled code at target/compiled/sample_dbt/models/staging/schema.yml/relationships_stg_center_company_id__id__ref_stg_company_.sql
    09:08:07  
    09:08:07  Done. PASS=4 WARN=0 ERROR=1 SKIP=0 TOTAL=5
    
  • Add not_null test (No data fails the not_null test, Just look at the order)

    09:15:45  5 of 6 START test relationships_stg_center_company_id__id__ref_stg_company_ .... [RUN]
    09:15:46  5 of 6 FAIL 1 relationships_stg_center_company_id__id__ref_stg_company_ ........ [FAIL 1 in 0.89s]
    09:15:46  6 of 6 START sql table model temp.int_center ............................. [RUN]
    09:15:48  6 of 6 OK created sql table model temp.int_center ........................ [CREATE TABLE (4.0 rows, 0 processed) in 1.61s]
    

After changing int_center as shown below, it behaves as expected.
It seems that relationships tests are only skipped when all downstream models referenced by the test are present.

-- depends-on: {{ ref('stg_company') }}

WITH 
source AS (
    SELECT
        *
    FROM {{ ref('stg_center') }}
)

SELECT
    *
FROM source
1 of 5 START sql view model temp.stg_center .............................. [RUN]
1 of 5 OK created sql view model temp.stg_center ......................... [CREATE VIEW (0 processed) in 1.14s]
2 of 5 START sql view model temp.stg_company ............................. [RUN]
2 of 5 OK created sql view model temp.stg_company ........................ [CREATE VIEW (0 processed) in 0.64s]
3 of 5 START sql view model temp.int_company ............................. [RUN]
3 of 5 OK created sql view model temp.int_company ........................ [CREATE VIEW (0 processed) in 0.82s]
4 of 5 START test relationships_stg_center_company_id__id__ref_stg_company_ .... [RUN]
4 of 5 FAIL 1 relationships_stg_center_company_id__id__ref_stg_company_ ........ [FAIL 1 in 0.93s]
5 of 5 SKIP relation temp.int_center ..................................... [SKIP]
1 Like