John Walsh
03/24/2026, 12:11 PMdata_tests:
# Monitor status distribution per employer
- elementary.dimension_anomalies:
arguments:
dimensions:
- status
- employer_id
time_bucket:
period: month
count: 1
training_period:
period: month
count: 7
detection_period:
period: month
count: 1
exclude_detection_period_from_training: true
what I was hoping it would do is create buckets on the combination of employer_id and status and the time grouping
however when I run the test and then check the elementary tables for my table, it only lists employer_id as a dimension
select distinct dimension
from elementary.data_monitoring_metrics
where full_table_name = 'my_table';
select distinct result_row::jsonb ->> 'dimension'
from elementary.test_result_rows
where result_row::jsonb ->> 'full_table_name' = 'my_table'
can you only define one dimension per test?kapa.ai
03/24/2026, 12:11 PMdimension_anomalies test, but the behavior is important to understand: when you list multiple dimensions, Elementary monitors the combination of those dimensions together, not each one separately.
So with your config:
dimensions:
- status
- employer_id
Elementary will group by the combination (status, employer_id) — e.g., "active; employer_123" — and monitor row counts for each unique pair. [dimensions config]
This is confirmed by Elementary support:
> "When configured in this way the test is checking the combination of those 2 dimensions together and not separately." [Slack discussion]
The fact that you're only seeing employer_id in your query results is unexpected given this behavior — it may be worth checking whether the test ran correctly or if there's a data issue. But the design intent is that both dimensions should appear as a combined dimension value.
If you want to monitor each dimension independently, you should define two separate tests:
data_tests:
- elementary.dimension_anomalies:
arguments:
dimensions:
- status
time_bucket:
period: month
count: 1
training_period:
period: month
count: 7
detection_period:
period: month
count: 1
- elementary.dimension_anomalies:
arguments:
dimensions:
- employer_id
time_bucket:
period: month
count: 1
training_period:
period: month
count: 7
detection_period:
period: month
count: 1
[Slack discussion]
So to directly answer your question: no, you're not limited to one dimension per test — but multiple dimensions in one test produce a joint grouping, not independent monitoring per dimension. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
03/24/2026, 12:14 PMThe fact that you're only seeinghow should i confirm/troubleshoot this?in your query results is unexpected given this behavior — it may be worth checking whether the test ran correctly or if there's a data issueemployer_id
kapa.ai
03/24/2026, 12:14 PMemployer_id as a dimension instead of the combined (status, employer_id) value: 1. Check if metrics are actually being collected Query data_monitoring_metrics to see what's being stored for your table:
SELECT
bucket_end,
dimension,
dimension_value,
metric_value
FROM elementary.data_monitoring_metrics
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;
This will show you exactly what dimension combinations are being recorded and whether there are gaps in the data. [Anomaly Troubleshooting] 2. Check the anomaly score calculations SELECT
metric_name,
latest_metric_value,
training_avg,
training_stddev,
anomaly_score,
is_anomaly
FROM elementary.metrics_anomaly_score
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;
This will confirm whether anomaly detection is running correctly and on the right dimension values. [Anomaly Troubleshooting] 3. Check the test results table SELECT *
FROM elementary.elementary_test_results
WHERE test_short_name = 'dimension_anomalies'
ORDER BY detected_at DESC
LIMIT 10;
Look at the test_sub_type column — it should show dimension, not generic. If it shows generic, that indicates the test configuration may not be picked up correctly (this is a known issue reported by community members). [Slack thread] 4. Try a force backfill If metrics seem stale or incomplete, re-run the test with:
dbt test --select your_model --vars '{"force_metrics_backfill": true}'
This forces Elementary to recalculate and re-store metrics from scratch. [Slack thread] 5. Check the dbt logs Review your dbt/dbt.log file for any compilation errors or warnings related to the dimension_anomalies test. Compilation errors can silently prevent metrics from being written to data_monitoring_metrics. [Anomaly Troubleshooting]
Also note: there is a known bug where dimension_anomalies tests don't always pick up configuration from the model level (e.g., timestamp_column). If you're setting any config at the model level rather than directly in the test arguments, try moving it into the test arguments explicitly. [Slack thread] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
03/24/2026, 12:16 PMdimension value is employer_idkapa.ai
03/24/2026, 12:16 PMdimension_anomalies works with multiple dimensions, the expected behavior is that the dimension column in data_monitoring_metrics should reflect the combined dimension expression (e.g., "status; employer_id"), not just one of the two columns.
Seeing only employer_id suggests one of the following:
1. A previous test run with only employer_id as a dimension is still in the table
If you previously ran the test with only employer_id configured, those older rows would still be in data_monitoring_metrics. Check whether the rows showing employer_id are from recent runs or older ones:
SELECT
bucket_end,
updated_at,
dimension,
dimension_value,
metric_value
FROM elementary.data_monitoring_metrics
WHERE full_table_name = 'my_table'
ORDER BY updated_at DESC;
2. The current test configuration isn't being picked up correctly
Try running with a force backfill to ensure the latest config is applied:
dbt test --select your_model --vars '{"force_metrics_backfill": true}'
Then re-run query 1 and check if the dimension column now shows the combined value. [Anomaly Troubleshooting]
3. Check the test results to confirm the test is running as dimension subtype
SELECT *
FROM elementary.elementary_test_results
WHERE test_short_name = 'dimension_anomalies'
ORDER BY detected_at DESC
LIMIT 5;
The test_sub_type should be dimension. If it's generic, the test configuration may not be correctly recognized. [Slack thread]
The knowledge sources don't explicitly document a case where only one of two configured dimensions appears — so this is likely either a stale data issue or a configuration not being applied correctly. The force backfill + checking updated_at timestamps should help you narrow it down. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 9:43 AMdata_tests:
# Monitor status distribution per employer
- elementary.dimension_anomalies:
arguments:
dimensions:
- status
- employer_id
- elementary_timestamp_override
time_bucket:
period: month
count: 1
training_period:
period: month
count: 7
detection_period:
period: month
count: 1
exclude_detection_period_from_training: truekapa.ai
04/09/2026, 9:43 AMdimension_anomalies anomaly-detection test that:
• Groups rows by the combination of:
◦ status
◦ employer_id
◦ elementary_timestamp_override
(multiple dimensions are treated as a joint key, e.g. "active; employer_123; 2026-03-01"). [dimensions config; dimension_anomalies behavior]
• Builds monthly time buckets (time_bucket: period: month, count: 1), so each bucket is one full calendar month. [time_bucket]
• Counts rows per (status, employer_id, elementary_timestamp_override, month) and monitors how those counts change over time. [dimension_anomalies intro]
• Uses:
◦ training_period: 7 months
◦ detection_period: 1 month
◦ exclude_detection_period_from_training: true so the detection month is not used to compute the expected range. [training_period; exclude_detection_period_from_training] Which months are training vs detection? Elementary always works on complete time buckets. With time_bucket: month and detection_period: 1 month, the *detection period is the last fully completed month*; incomplete “current” month is not used. [detection_period; Slack explanation]
Assume today is somewhere in April 2026 and April is not yet complete:
• Detection month (1 month):
◦ Last completed month → March 2026 (bucket 2026‑03‑01 → 2026‑04‑01).
• Training months (7 months), with `exclude_detection_period_from_training: true`:
◦ The 7 full months before March 2026:
▪︎ August 2025 – February 2026 (Aug, Sep, Oct, Nov, Dec 2025; Jan, Feb 2026).
So for each (status, employer_id, elementary_timestamp_override) combination, the test:
1. Takes the row count in March 2026 (detection bucket).
2. Compares it to the distribution of row counts from Aug 2025–Feb 2026 (training buckets), excluding March from training because of exclude_detection_period_from_training: true. [training_period; exclude_detection_period_from_training]
If you run the same config later (e.g., in May 2026, once April is complete), the detection month would shift to April 2026, and the 7‑month training window would shift to September 2025 – March 2026, always keeping 7 historical full months and 1 latest full month for detection. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 9:48 AM"training_start": "2025-10-01T00:00:00",
"training_end": null,kapa.ai
04/09/2026, 9:48 AMtest_result_rows.result_row is not fully aligned with the conceptual description of training/detection periods, and there are known quirks here.
From the knowledge sources:
• There is a known issue where training_end can be null in test_result_rows.result_row, even when is_anomalous = true. A community member explicitly asked if this is a known bug and how to reliably coalesce training_end from other fields, which implies this behavior is not currently well-documented or fully correct. [Slack discussion]
• Elementary is actively investigating correctness issues around exclude_detection_period_from_training, including cases where the detection bucket appears to fall within the training window despite the flag being set. [Slack investigation]
So:
• Conceptually, with your config, you should have a 7‑month training window and a 1‑month detection window, with the detection month excluded from training. [training_period; exclude_detection_period_from_training]
• But the JSON fields in test_result_rows are not always reliable, and training_end = null is a known symptom of that.
To understand what’s actually happening in your run, the recommended approach from the docs and community is to ignore training_end in test_result_rows and instead:
1. Inspect metrics_anomaly_score directly:SELECT
bucket_start,
bucket_end,
training_start,
training_end,
training_set_size,
metric_value,
is_anomalous
FROM elementary.metrics_anomaly_score
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;This table is the authoritative source for how the training window was applied. [Anomaly troubleshooting]
2. Cross‑check with data_monitoring_metrics to see which buckets exist and which one is the latest detection bucket:SELECT
bucket_start,
bucket_end,
dimension,
dimension_value,
metric_value
FROM elementary.data_monitoring_metrics
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;
``` [[Anomaly troubleshooting](https://docs.elementary-data.com/data-tests/anomaly-detection-tests/Anomaly-troubleshooting-guide#page-title)]
Because the knowledge sources explicitly say there are open investigations and bugs around both exclude_detection_period_from_training and the training metadata fields, I cannot confidently reconcile your `training_start`/`training_end = null` purely from docs — it’s likely a manifestation of those known issues rather than your config being wrong. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 9:56 AMkapa.ai
04/09/2026, 9:56 AMmetrics_anomaly_score when something earlier in the pipeline isn’t satisfied. Based on the knowledge, here’s how to narrow it down for your dimension_anomalies test: 1. Confirm metrics are being collected at all You already saw your table in data_monitoring_metrics, but run this to be explicit:
SELECT
bucket_end,
dimension,
dimension_value,
metric_name,
metric_value
FROM elementary.data_monitoring_metrics
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;
If no rows come back, metrics_anomaly_score will also be empty. In that case, the test isn’t writing metrics (config / compilation issue). [Metrics table purpose]
You’ve said you do see rows there, so move on. 2. Check if there’s “enough data to calculate anomaly” Elementary only creates rows in metrics_anomaly_score once there are enough training points (≥ 7). Before that, you’ll see “Not enough data to calculate anomaly score” and metrics_anomaly_score stays empty. [Anomaly troubleshooting]
Look at the number of distinct buckets for your table:
SELECT
COUNT(DISTINCT bucket_end) AS buckets,
MIN(bucket_end) AS first_bucket,
MAX(bucket_end) AS last_bucket
FROM elementary.data_monitoring_metrics
WHERE full_table_name = 'my_table';
If buckets < 7, you won’t see anything in metrics_anomaly_score yet. 3. Verify the test is recognized as dimension_anomalies If the test is mis‑parsed as a generic test, it may not flow into metrics_anomaly_score as expected.
SELECT
test_name,
test_sub_type,
detected_at,
status
FROM elementary.elementary_test_results
WHERE test_short_name = 'dimension_anomalies'
AND full_table_name = 'my_table'
ORDER BY detected_at DESC
LIMIT 10;
• test_sub_type should be dimension.
• If it’s generic, there’s a config recognition issue. [Dimension subtype issue] 4. Force metrics backfill with your current config If you changed the test recently, older metrics may not match the new config and scoring may not have been recomputed.
Run:
dbt test --select my_table --vars '{"force_metrics_backfill": true}'
Then re‑check:
SELECT *
FROM elementary.metrics_anomaly_score
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;
For dimension_anomalies, forcing backfill is a recommended step when config changes or results look off. [Force backfill] 5. If still empty: likely a known limitation/bug The knowledge sources mention:
• Cases where anomaly tests (especially dimension_anomalies) populate data_monitoring_metrics but never produce rows in metrics_anomaly_score, even though the config looks correct. [Dimension anomalies issues]
• Open bugs around dimension_anomalies configuration handling and training metadata. [Known bug]
So if:
• data_monitoring_metrics has ≥ 7 buckets for your table,
• elementary_test_results shows test_sub_type = 'dimension',
• you’ve run with force_metrics_backfill,
and your table still doesn’t appear in metrics_anomaly_score, then based on the docs and threads I have, this is most likely hitting one of those known dimension_anomalies issues rather than a misconfiguration on your side.
In that case, the next step would be to share:
• Your exact test YAML,
• A sample of data_monitoring_metrics for my_table,
• And the elementary_test_results rows for that test
in the Elementary Slack so the team can confirm if it’s the known bug or something schema‑specific. The knowledge sources don’t provide a more specific fix beyond the checks above. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 11:07 AMkapa.ai
04/09/2026, 11:07 AMdimension_anomalies and some column tests.
Here’s what it means and what you can do, based only on what’s documented:
1. data_monitoring_metrics is the “raw metrics” store
If your table appears there, it means the anomaly test is running and writing metric points (per bucket / dimension). [Metrics table purpose]
2. metrics_anomaly_score is only populated when scoring is possible
Elementary only writes rows there once it can actually compute anomaly scores from the metrics in data_monitoring_metrics. If there aren’t enough valid training points (typically fewer than 7), you’ll see “Not enough data to calculate anomaly score” and no rows in metrics_anomaly_score. [Anomaly troubleshooting]
3. Some test types don’t always show up in metrics_anomaly_score even when metrics exist
The sources explicitly mention that for certain anomaly tests (notably all_columns_anomalies, and in several threads dimension_anomalies), users see:This is described as different behavior / a limitation rather than a clear misconfiguration.
◦ Results in elementary_test_results and data_monitoring_metrics
◦ But nothing in metrics_anomaly_score, even after history has built up. [All columns vs volume]
1. *What you can reliably check now*Since your table is in data_monitoring_metrics but not in metrics_anomaly_score, the docs suggest these concrete checks:SELECT
COUNT(DISTINCT bucket_end) AS buckets,
MIN(bucket_end) AS first_bucket,
MAX(bucket_end) AS last_bucket
FROM elementary.data_monitoring_metrics
WHERE full_table_name = 'my_table';If buckets < 7, metrics_anomaly_score staying empty is expected. [Anomaly troubleshooting]SELECT
test_name,
test_sub_type,
detected_at,
status
FROM elementary.elementary_test_results
WHERE full_table_name = 'my_table'
ORDER BY detected_at DESC
LIMIT 10;For dimension_anomalies, test_sub_type should be `dimension`; if it’s generic, config recognition issues can prevent proper scoring. [Slack subtype issue]dbt test --select my_table --vars '{"force_metrics_backfill": true}'Then re-check `metrics_anomaly_score`:SELECT *
FROM elementary.metrics_anomaly_score
WHERE full_table_name = 'my_table'
ORDER BY bucket_end DESC;[Force backfill]
◦ Verify how many buckets you actually have (to rule out “not enough data”):
◦ Confirm the test is recognized as an anomaly subtype:
◦ Force recomputation with your current config:
If, after:
• ≥ 7 buckets in data_monitoring_metrics,
• test_sub_type is correct,
• and a force_metrics_backfill run,
your table still never appears in metrics_anomaly_score, the knowledge sources indicate this is likely hitting one of the known limitations/bugs around anomaly scoring (especially for non-volume tests), rather than something you can fix purely via config. In that case, the recommended next step (per the Slack threads) is to share those query outputs in the Elementary Slack so the team can confirm if it matches the known issues. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 11:32 AMkapa.ai
04/09/2026, 11:32 AManomaly_score, training_avg, training_stddev, training_start, training_end, is_anomaly) are in metrics_anomaly_score. [Anomaly troubleshooting; Stddev location]
• Raw metrics per bucket and dimension are in data_monitoring_metrics. [Metrics table]
• Per‑test temporary __anomaly_scores tables also contain training_avg, training_stddev, min_metric_value, max_metric_value, anomaly_score, etc., but they’re per‑test and not centralized. [Per‑test scores]
• full_table_name is stored in these tables as DATABASE.SCHEMA.TABLE. [Troubleshooting guide]
So the most reusable base is metrics_anomaly_score joined to data_monitoring_metrics (if you want the original metric row). 2. Example query to build your table This example assumes:
• You want one row per bucket per dimension where an anomaly was evaluated.
• “Detection period start/end” = the bucket’s bucket_start / bucket_end.
• “Training period start/end” = training_start / training_end.
• “Detected value” = the metric value in the detection bucket.
• “Training value” = the training average (training_avg).
You can derive schema and table_name by splitting full_table_name if needed (syntax will vary by warehouse).
SELECT
-- Split full_table_name into database / schema / table as needed.
mas.full_table_name,
-- Example for warehouses that support SPLIT_PART; adjust for yours:
SPLIT_PART(mas.full_table_name, '.', 2) AS schema_name,
SPLIT_PART(mas.full_table_name, '.', 3) AS table_name,
mas.column_name AS column,
mas.dimension,
mas.dimension_value,
mas.is_anomaly AS is_anomalous,
-- Detection period = the bucket being scored
mas.bucket_start AS detection_period_start,
mas.bucket_end AS detection_period_end,
-- Training window used for this score
mas.training_start AS training_period_start,
mas.training_end AS training_period_end,
-- Detected vs training values
mas.latest_metric_value AS detected_value,
mas.training_avg AS training_value,
mas.anomaly_score
FROM <elementary_schema>.metrics_anomaly_score AS mas
-- Optional: join back to data_monitoring_metrics if you need extra raw fields
-- LEFT JOIN <elementary_schema>.data_monitoring_metrics dmm
-- ON mas.id = dmm.id
-- Filter to only anomalous points, or drop this to see all scored buckets
WHERE mas.anomaly_score IS NOT NULL
-- AND mas.is_anomaly = TRUE -- if you only want flagged anomalies
ORDER BY
mas.full_table_name,
mas.column_name,
mas.dimension,
mas.dimension_value,
mas.bucket_end DESC;
This uses only fields that the docs explicitly show as present in `metrics_anomaly_score`: full_table_name, column_name, dimension, dimension_value, metric_name, latest_metric_value, training_avg, training_stddev, training_start, training_end, training_set_size, anomaly_score, is_anomaly, bucket_start, bucket_end, updated_at. [metrics_anomaly_score model; Stddev query example] 3. Notes / limitations • If your table doesn’t appear in metrics_anomaly_score, but does in data_monitoring_metrics, it may be because there aren’t enough training points yet (fewer than 7 buckets) or you’re hitting one of the known dimension_anomalies quirks where scoring isn’t materialized there. [Anomaly troubleshooting; Behavior differences]
• The exact string splitting for schema / table_name must match your warehouse’s SQL functions; the knowledge sources don’t prescribe a specific pattern, only that full_table_name is DB.SCHEMA.TABLE. [Troubleshooting guide]
Within those constraints, the query above is the documented way to assemble the view you described from the Elementary schema. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:18 PMkapa.ai
04/09/2026, 12:19 PMelementary config at the top level of models:, not nested under your project name:
models:
my_project:
materialized: "{{ 'table' if target.name == 'prod' else 'view' }}"
elementary:
+schema: "elementary"
This means dbt will create Elementary tables in a schema named <target_schema>_elementary (e.g. dev_elementary when your target schema is dev). [Quickstart package] 2. Handle generate_schema_name if you have a custom macro If your project has a custom generate_schema_name macro, it may override Elementary's schema config and send tables to the wrong place. You need to explicitly handle the elementary package:
{% macro generate_schema_name(custom_schema_name, node) -%}
{% if node.package_name == 'elementary' %}
{% set schema_name = node.package_name | trim %}
{% else %}
{% set schema_name = generate_schema_name_for_env(custom_schema_name, node) %}
{% endif %}
{{ schema_name }}
{%- endmacro %}
After updating the macro, re-run dbt run --select elementary to recreate the tables in the correct schema. [Slack discussion] 3. Disable hooks in local dev (optional but recommended) To avoid slowing down local runs, you can disable the on-run-end hooks that upload artifacts, while still allowing Elementary tests to run:
vars:
disable_run_results: "{{ target.name not in ['prod','staging','dev'] }}"
disable_tests_results: "{{ target.name not in ['prod','staging','dev'] }}"
disable_dbt_artifacts_autoupload: "{{ target.name not in ['prod','staging','dev'] }}"
disable_dbt_invocation_autoupload: "{{ target.name not in ['prod','staging','dev'] }}"
[Dev/prod configuration] 4. Create the Elementary tables in your dev target Once the config is in place, run:
dbt run --select elementary --target dev
This creates the Elementary tables in your dev schema. If you skip this step, the hooks will fail with "Unable to insert rows to non-existent table." [BigQuery Slack thread] 5. Update profiles.yml for edr CLI (if you use it) The edr CLI does not respect your custom generate_schema_name macro — it only reads the schema from the elementary profile in profiles.yml. Add a top-level elementary profile pointing to your dev schema:
elementary:
target: dev
outputs:
dev:
type: <your_warehouse_type>
schema: dev_elementary # must match where Elementary tables are actually created
# ... other connection details
[Slack reference] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:24 PMkapa.ai
04/09/2026, 12:24 PMelementary schema — is a known issue when a custom generate_schema_name macro is involved, and it also affects dbt Cloud CLI users.
Here are the things to check: 1. Do you have a custom generate_schema_name macro? This is the most common cause. If your project has a custom generate_schema_name macro, it can override the +schema: elementary config and send tables to the wrong place. You need to explicitly handle the elementary package in that macro:
{% macro generate_schema_name(custom_schema_name, node) -%}
{% if node.package_name == 'elementary' %}
{% set schema_name = node.package_name | trim %}
{% else %}
{% set schema_name = generate_schema_name_for_env(custom_schema_name, node) %}
{% endif %}
{{ schema_name }}
{%- endmacro %}
After updating, re-run dbt run --select elementary. [Slack discussion] 2. Check the placement of the elementary config in dbt_project.yml The elementary block must be at the top level of models:, not nested under your project name. A common mistake is nesting it:
# ❌ Wrong - nested under your project
models:
my_project:
elementary:
+schema: elementary
# ✅ Correct - top-level sibling of your project
models:
my_project:
...
elementary:
+schema: elementary
If it's nested incorrectly, dbt will warn There are 1 unused configuration paths and ignore the schema setting. [Slack thread] 3. dbt Cloud CLI and custom schemas The knowledge sources note that in dbt Cloud CI environments, Elementary models can end up in the wrong schema (e.g., the temporary PR schema or the default target schema) on the first run, and only resolve correctly after a production job has run. This is a known issue specific to dbt Cloud. [GitHub issue]
The knowledge sources don't contain enough information to give a dbt Cloud CLI-specific workaround beyond the macro fix above. If fixing the generate_schema_name macro doesn't resolve it, I'd recommend raising it in the Elementary Slack with your exact dbt_project.yml config and macro, as the team has investigated similar dbt Cloud schema resolution issues there. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:25 PM{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if custom_schema_name is not none and target.name == 'production' -%}
{{ custom_schema_name | trim }}
{%- else -%}
{{ default_schema }}
{%- endif -%}
{%- endmacro %}
@kapa.aikapa.ai
04/09/2026, 12:26 PMproduction target: custom_schema_name is "elementary" (from your +schema: elementary config), so Elementary tables land in a schema literally named elementary. ✅
• In any other target (e.g. dev): the else branch fires and returns default_schema (your dbt Cloud target schema), ignoring custom_schema_name entirely. This is why Elementary tables land in your default dev schema instead of dev_elementary or similar. ❌
To fix this so Elementary gets its own schema in dev too, you need to special-case the elementary package. Based on the patterns recommended by Elementary support: [Slack discussion]
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if node.package_name == 'elementary' and custom_schema_name -%}
{{ default_schema }}_{{ custom_schema_name | trim }}
{%- elif custom_schema_name is not none and target.name == 'production' -%}
{{ custom_schema_name | trim }}
{%- else -%}
{{ default_schema }}
{%- endif -%}
{%- endmacro %}
This means:
• All targets: Elementary tables go to <target_schema>_elementary (e.g. dev_elementary in dev, prod_elementary in production).
• Production, non-Elementary models: still use the literal custom_schema_name as before.
• Dev, non-Elementary models: still fall back to default_schema as before.
After updating the macro, re-run:
dbt run --select elementary
to recreate the Elementary tables in the correct schema. [Slack discussion]
If you'd prefer Elementary to use a fully literal schema name (not prefixed with the target schema), you can return just custom_schema_name | trim in the Elementary branch instead. [OSS FAQ] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:28 PMdbt test --select <my_model>
dbt run --select elementary
that the artifacts generated by my local test run is what will get consumed by my local run of the elementary tableskapa.ai
04/09/2026, 12:28 PMdbt test --select <my_model> — runs your tests and triggers the elementary.handle_tests_results on-run-end hook, which writes results into elementary_test_results and data_monitoring_metrics (for anomaly tests) in whatever schema Elementary is configured to use in your current target. [on-run-end hooks]
2. dbt run --select elementary — runs the Elementary dbt models, which read from those same tables (e.g. data_monitoring_metrics → metrics_anomaly_score) to produce the derived views and aggregations. Since both commands run against the same target/schema, the Elementary models will consume exactly the metrics and results that your local test run just wrote. [dbt artifacts]
So yes — as long as both commands run against the same dbt target (which they will by default in dbt Cloud CLI), your local test results are what get consumed by the Elementary models. There's no cross-environment mixing unless you explicitly switch targets between the two commands. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:29 PMdbt run --select elementary after every test run or does the end hook consume the artifacts and append records to the elementary tables? @kapa.aikapa.ai
04/09/2026, 12:30 PMdbt run --select elementary after every test run.
The on-run-end hooks handle appending results automatically. Specifically, after each dbt test (or dbt run / dbt build), the hooks fire and write directly to the Elementary tables:
• elementary_test_results — via the elementary.handle_tests_results hook
• dbt_run_results — via the elementary.upload_run_results hook
• Metadata tables (dbt_models, dbt_tests, etc.) — also updated via on-run-end
All of this happens without needing to explicitly run dbt run --select elementary. [on-run-end hooks; dbt artifacts]
dbt run --select elementary is only needed in two situations:
1. First-time setup — to create the Elementary tables in your schema.
2. After a minor version upgrade — when there are schema changes to the Elementary tables. [Slack confirmation]
For your regular local workflow, just running dbt test --select <my_model> is sufficient to populate the Elementary tables with your test results. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:31 PMselect *
from <dev_schema>.metrics_anomaly_scorekapa.ai
04/09/2026, 12:32 PMmetrics_anomaly_score is empty in your dev schema: Step 1: Confirm metrics are being written at all SELECT
COUNT(DISTINCT bucket_end) AS buckets,
MIN(bucket_end) AS first_bucket,
MAX(bucket_end) AS last_bucket,
full_table_name
FROM <dev_schema>.data_monitoring_metrics
GROUP BY full_table_name
ORDER BY buckets DESC;
• If this is also empty, your anomaly tests aren't writing metrics at all — check that your dbt test is actually running anomaly tests and that the on-run-end hooks are firing (look for Elementary: Uploading test results in your dbt.log). [Anomaly troubleshooting]
• If this has rows, continue to Step 2. Step 2: Check if you have enough training points metrics_anomaly_score only gets populated once there are at least 7 training data points. If you have fewer than 7 buckets in data_monitoring_metrics for a given table, you'll see "Not enough data to calculate anomaly score" and metrics_anomaly_score stays empty. [Anomaly troubleshooting]
Your test uses time_bucket: month, so you'd need at least 7 months of data in data_monitoring_metrics before scores appear. Step 3: Confirm the test is recognized as an anomaly subtype SELECT
test_name,
test_short_name,
test_sub_type,
detected_at,
status
FROM <dev_schema>.elementary_test_results
ORDER BY detected_at DESC
LIMIT 10;
For dimension_anomalies, test_sub_type should be dimension. If it shows generic, the test configuration isn't being picked up correctly, which can prevent scoring. [Slack subtype issue] Step 4: Force a metrics backfill dbt test --select <your_model> --vars '{"force_metrics_backfill": true}'
Then re-check metrics_anomaly_score. This forces Elementary to recompute scores from the existing metrics in data_monitoring_metrics. [Force backfill] Step 5: Check that hooks are actually firing in dev Make sure none of these vars are set to true in your dev environment, as they would prevent results from being written:
vars:
disable_run_results: true
disable_tests_results: true
disable_dbt_artifacts_autoupload: true
disable_dbt_invocation_autoupload: true
Also check your dbt.log for the lines Elementary: Uploading test results — if they're missing, the hooks didn't run. [Disabled vars] Given your earlier conversation, the most likely culprit is Step 2 — since your test uses monthly buckets and you're running locally in dev, you may simply not have accumulated 7 months of metric history in your dev schema yet. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:33 PM8,2025-09-01 00:00:00.000000,2026-04-01 00:00:00.000000,<mymodel1>
7,2025-09-01 00:00:00.000000,2026-03-01 00:00:00.000000,<mymodel2>kapa.ai
04/09/2026, 12:34 PM<mymodel1>: 8 buckets, spanning Sept 2025 → April 2026
• <mymodel2>: 7 buckets, spanning Sept 2025 → March 2026
Both models have ≥ 7 buckets, so the "not enough training data" threshold should be met. [Anomaly troubleshooting]
This means the empty metrics_anomaly_score is likely not a training data volume issue. Move on to the remaining steps: Next: Step 3 — Check test subtype SELECT
test_name,
test_short_name,
test_sub_type,
detected_at,
status
FROM <dev_schema>.elementary_test_results
WHERE full_table_name LIKE '%mymodel1%'
OR full_table_name LIKE '%mymodel2%'
ORDER BY detected_at DESC
LIMIT 10;
For dimension_anomalies, test_sub_type must be dimension. If it shows generic, the test config isn't being recognized correctly and scoring won't happen. [Slack subtype issue] Then: Step 4 — Force backfill dbt test --select <your_model> --vars '{"force_metrics_backfill": true}'
Then re-check metrics_anomaly_score. [Force backfill]
Share the output of the Step 3 query and I can help narrow it down further. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:37 PMdimension_anomalies,dimension,2026-04-09 12:10:31.000000,fail
column_anomalies,standard_deviation,2026-04-09 12:09:48.000000,fail
column_anomalies,standard_deviation,2026-04-09 12:09:48.000000,fail
column_anomalies,zero_count,2026-04-09 12:09:48.000000,fail
column_anomalies,sum,2026-04-09 12:09:48.000000,fail
column_anomalies,average,2026-04-09 12:09:48.000000,fail
column_anomalies,min,2026-04-09 12:09:48.000000,pass
column_anomalies,average,2026-04-09 12:09:48.000000,fail
column_anomalies,max,2026-04-09 12:09:48.000000,fail
column_anomalies,max,2026-04-09 12:09:48.000000,failkapa.ai
04/09/2026, 12:37 PMdimension_anomalies test is showing test_sub_type = dimension (not generic), which means the test configuration is being recognized correctly. [Slack subtype issue]
So the test is running and recognized, but metrics_anomaly_score is still empty. The next step is: Try a force backfill dbt test --select <your_model> --vars '{"force_metrics_backfill": true}'
Then re-check:
SELECT *
FROM <dev_schema>.metrics_anomaly_score
WHERE full_table_name LIKE '%mymodel1%'
OR full_table_name LIKE '%mymodel2%'
ORDER BY bucket_end DESC;
If it's still empty after the force backfill, this aligns with the known pattern documented in the community where dimension_anomalies tests populate data_monitoring_metrics but do not produce rows in metrics_anomaly_score, even when configuration and data volume look correct. [Dimension anomalies issues; Behavior differences]
At that point, the knowledge sources don't provide a further self-service fix — the recommended next step would be to share your test YAML, the data_monitoring_metrics sample, and the elementary_test_results rows with the Elementary Slack team for them to confirm if it's the known bug. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 12:42 PMkapa.ai
04/09/2026, 12:43 PMdata_monitoring_metrics has ≥ 7 buckets for both models
• ✅ test_sub_type = dimension (config is recognized correctly)
• ✅ Force backfill didn't resolve it
• ❌ metrics_anomaly_score remains empty
This matches the known pattern documented in the community where dimension_anomalies tests populate data_monitoring_metrics but never produce rows in metrics_anomaly_score. [Dimension anomalies issues; Behavior differences]
The best place to get help is the Elementary community Slack — the knowledge sources show that the Elementary team actively responds there and has investigated similar dimension_anomalies issues directly with users. When you post, include:
• Your exact test YAML
• A sample of data_monitoring_metrics for your table
• The elementary_test_results rows for the test
• Your Elementary dbt package version (from packages.yml)
There is also an open GitHub issue tracking related dimension_anomalies bugs that you can comment on or react to, which helps the team prioritize: [GitHub issue #1170] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.John Walsh
04/09/2026, 3:06 PMElementary community Slackwhich channel or user should i report this issue to?
kapa.ai
04/09/2026, 3:06 PM#general or #support style channel with ID C02CTC89LAX — but I can't confirm the exact channel name from the sources provided.
What I can say is that the Elementary team is reachable via their community Slack, and the knowledge sources also mention you can DM the @elementary.ai app for 1-to-1 help. [Slack thread]
For the most accurate channel to post in, I'd recommend joining the Elementary community Slack (via elementary-data.com) and checking the channel list there directly. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.