Skip to content

dbt source relationships tests are not modeled as asset checks #33982

Description

@themattmorris

What's the issue?

When DagsterDbtTranslatorSettings(enable_source_tests_as_checks=True) is set, single-dependency source tests (not_null, unique) are correctly modeled as Dagster asset checks. However, relationships tests defined on a source column are silently dropped — no asset check is ever created for them.

The tests still execute as part of dbt build, so data-quality enforcement is intact, but they are invisible in Dagster: no asset-check tile, no lineage, and a failure surfaces only as the parent asset failing rather than as a named check.

This is specific to source tests with more than one dependency. The equivalent relationships test defined on a model column works correctly.

What did you expect to happen?

The source relationships test is modeled as an asset check attached to the "from" source asset (foo), consistent with how a relationships test on a model column is attached to its model.

How to reproduce?

sources.yml:

version: 2
sources:
  - name: my_source
    schema: my_schema
    tables:
      - name: foo
        columns:
          - name: id
            data_tests: [not_null, unique]        # -> becomes an asset check  ✅
          - name: bar_id
            data_tests:
              - relationships:                      # -> NO asset check created ❌
                  arguments:
                    to: source('my_source', 'bar')
                    field: id
      - name: bar
        columns:
          - name: id
            data_tests: [not_null, unique]

dbt registers the test correctly (dbt ls --resource-type test --select source:my_source.foo lists source_relationships_my_source_foo_id__id__source_my_source_bar_), but it does not appear as an asset check in Dagster.

There is no relationship asset check in dagster:

Image

Dagster version

1.12.14

Deployment type

Dagster Cloud

Deployment details

No response

Additional information

I understand the issue is not necessary and can go straight to the PR, but wanted to capture the problem we were seeing. I will open a PR with the fix!

Root cause

In dagster_dbt/asset_utils.py, the function that maps a test to an AssetCheckKey determines the attached asset as follows:

# asset_utils.py (~L982-L1026)
upstream_unique_ids = set(test_resource_props["depends_on"]["nodes"])
attached_node_unique_id = test_resource_props.get("attached_node")

# If the test is singular, infer the attached node from the upstream nodes.
if len(upstream_unique_ids) == 1:
    [attached_node_unique_id] = upstream_unique_ids

# ... meta.dagster.ref fallback (searches manifest["nodes"] only) ...

if not attached_node_unique_id:
    return None

dbt populates attached_node for generic tests defined on models/seeds/snapshots, but leaves it None for tests defined on sources. For source tests this is normally rescued by the len(upstream_unique_ids) == 1 fallback — but a relationships test has two dependencies (the "from" table and the "to" table), so that branch never fires, attached_node_unique_id stays None, and the function returns None.

The config.meta.dagster.ref escape hatch does not help here either: its lookup loop iterates manifest["nodes"] only and never scans manifest["sources"], so a ref pointing at a source asset cannot resolve. (Arguably a second, related bug.)

Suggested fix

When attached_node is None and the test has multiple dependencies, fall back to the test's own anchor instead of giving up. The manifest carries enough to disambiguate a relationships test:

  • column_name (e.g. bar_id) and the test name / file_key_name identify the "from" source.
  • The to: argument identifies the other dependency.

Attaching the check to the "from" source would make source relationships tests behave like their model counterparts. Additionally, extending the meta.dagster.ref lookup to also search manifest["sources"] would give users an explicit override for the multi-dependency source case.

Message from the maintainers

Impacted by this issue? Give it a 👍! We factor engagement into prioritization.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions