Area: Ingestion Issues
Sub-Area: dbt Source Ingestion / Assertions
Issue
After running dbt source freshness and generating a sources.json file that shows passing freshness checks, users cannot find those freshness check results anywhere in the DataHub UI. The official documentation states that "We transfer dbt's freshness checks to DataHub's last-modified fields," but the transferred value is not visible in any UI tab — including the Summary, Stats, or Assertions tabs — leaving users uncertain whether ingestion succeeded or whether they are looking in the wrong place.
You Might Be Asking
- Where do dbt source freshness check results appear in the DataHub UI after ingestion?
- Is the "Status Last Updated" or "Last Updated" field in the Summary tab populated by dbt freshness checks?
- Why does my
sources.jsonshowstatus: passbut I see nothing in DataHub? - Do dbt source freshness checks create Assertions in DataHub?
- Is
run_results.jsonsupposed to capture freshness check results?
Root Cause
There are two distinct behaviors to understand here, both of which contribute to the confusion:
-
Source freshness checks do not create Assertions. The DataHub dbt ingestion source only creates Assertions from entries in
run_results.jsonwhoseunique_idstarts withtest.(i.e., standard dbt schema tests such asnot_null,unique, etc.). Source freshness results come fromdbt source freshnessand are recorded insources.json, notrun_results.json. As a result, even whenrun_results.jsonis provided to the ingestion recipe, it will never contain freshness check entries, and no Assertion entities will be created for them. -
The
max_loaded_attimestamp is stored in a field not shown in the UI. Themax_loaded_atvalue fromsources.jsonis mapped toSchemaMetadata.lastModifiedin the DataHub metadata model. However, the DataHub UI surfacesDatasetProperties.lastModified— a different field — in its Status/Summary section. Because the freshness timestamp is written toSchemaMetadata.lastModifiedrather thanDatasetProperties.lastModified, it is stored in the backend but is invisible through the web interface.
Error Messages
(No error is raised — ingestion completes successfully, but freshness data is silently not surfaced in the UI.)
Solution
-
Confirm ingestion completed successfully. Use the DataHub CLI to verify that the
lastModifiedfield was in fact ingested at the backend level:
Look for adatahub get --urn "urn:li:dataset:(urn:li:dataPlatform:dbt,<your-platform-instance>.<your-schema>.<your-table>,PROD)"lastModifiedvalue inside theschemaMetadataaspect. If it is populated with the expected timestamp, the freshness data was ingested correctly — it is simply not displayed in the UI. - Understand the current product gap. As of the time of this writing, dbt source freshness results are not exposed anywhere in the DataHub UI. This is a known gap tracked in the DataHub open-source project (see GitHub issue #15292). There is no configuration option or workaround to surface these results through the UI at this time.
-
Do not expect Assertions to be created from freshness checks. If your goal is to see assertion-style pass/fail results in DataHub, note that only standard dbt tests (entries in
run_results.jsonwithunique_idprefixed bytest.) are converted to DataHub Assertions. Source freshness checks are a separate dbt concept and are not processed through the same pipeline. Providingrun_results.jsonfromdbt testordbt buildwill create Assertions for schema tests only. -
Watch for a fix in a future DataHub release. A code change (PR #15491) has been proposed to correctly map the freshness timestamp to
DatasetProperties.lastModifiedso it becomes visible in the UI. Monitor the DataHub release notes and upgrade when the fix is available.
Understanding the "Synced" / "Last Updated" Fields in the UI
For reference, here is what each timestamp field in the DataHub UI actually represents for a dbt asset:
-
Synced — Derived from
systemMetadata.lastModified, which reflects the most recent time any metadata aspect was written to DataHub. This updates on every ingestion run regardless of freshness checks. -
Last Updated (DatasetProperties) — Populated by
DatasetProperties.lastModified. On a combined Snowflake+dbt view, this value typically comes from the Snowflake aspect, not from dbt freshness data. -
dbt freshness (
max_loaded_at) — Currently written toSchemaMetadata.lastModifiedonly, which has no corresponding UI display element.
Additional Notes
- This behavior applies to DataHub Cloud and open-source deployments using the DataHub dbt ingestion source.
- The documentation statement "We transfer dbt's freshness checks to DataHub's last-modified fields" is technically accurate but misleading: the value is stored, just not in a field the UI renders.
- If you are on a combined dbt + Snowflake ingestion view, the "Last Updated" timestamp visible in the UI is likely sourced from the Snowflake platform aspect, not from dbt freshness data.
- Using
run_results.jsonproduced bydbt testvs.dbt builddoes not affect freshness check behavior — neither will produce freshness Assertions, because freshness results are only insources.json. - A fix is in progress (see GitHub PR #15491). Until it is released and deployed, the only way to confirm a freshness timestamp was ingested is via the CLI
datahub getcommand inspecting the raw metadata.
Related Documentation
- dbt Ingestion Source — DataHub Docs
- Assertions Overview — DataHub Docs
- GitHub Issue #15292 — dbt freshness checks not visible in UI
- GitHub PR #15491 — Fix dbt freshness lastModified mapping
Tags: dbt, freshness-checks, ingestion, assertions, sources-json, run-results, lastModified, UI-gap, dbt-source, known-issue