Why this matters on call
Most dbt incidents end with "rebuild the broken model and everything that depends on it, and nothing else". Getting the selector wrong either misses a downstream table (stale data on a dashboard) or rebuilds the whole project during business hours (warehouse cost and lock contention). Check the selection with dbt ls first, then run it.
dbt ls --select <selector> --resource-type model --output name
Tip
Always preview with
dbt lsbeforedbt run --full-refreshor any command that targets production. It parses the project without touching the warehouse.
Graph operators
| Selector | Selects |
|---|---|
orders | The orders node only |
orders+ | orders and everything downstream |
+orders | orders and everything upstream |
+orders+ | Upstream, the node and downstream |
orders+1 | orders and its direct children only |
2+orders | orders and two generations of parents |
@orders | orders, its descendants, and all ancestors of those descendants (safe for CI builds of a changed model) |
Selection methods
| Selector | Selects |
|---|---|
path:models/staging/stripe or models/staging/stripe | Everything under a folder |
tag:nightly | Nodes tagged nightly |
source:stripe+ | Everything that reads from the stripe source |
source:stripe.charges+ | Downstream of one source table |
config.materialized:incremental | All incremental models |
resource_type:snapshot | All snapshots |
test_type:generic / test_type:singular | Generic (YAML) or singular (SQL file) tests |
package:dbt_utils | Nodes from one package |
exposure:weekly_sales+, +exposure:weekly_sales | Nodes feeding a dashboard or exposure (use + before to get parents) |
state:modified / state:new | Changed or added since the artifacts in --state |
result:error, result:fail, result:warn | Nodes with that status in the previous run's run_results.json |
Method names vary slightly by version; dbt ls --help and the selection docs for your version are the source of truth.
Union, intersection and exclusion
# Union: space-separated
dbt run --select tag:finance tag:sales
# Intersection: comma, no spaces
dbt run --select tag:nightly,config.materialized:incremental
# Exclude
dbt build --select models/marts --exclude tag:deprecated orders_legacy
Quote selectors in PowerShell and zsh if they contain + or *, for example --select "orders+".
Common support tasks
| Goal | Command |
|---|---|
| Rebuild one broken model and its downstream, with tests | dbt build --select orders+ |
| Rebuild only what failed last run | dbt retry (1.6+) |
| Rebuild failed nodes and their children from saved artifacts | dbt build --select result:error+ result:fail+ --state target/ |
| Full refresh one incremental model | dbt run --select orders --full-refresh |
| Run against a non-default target | dbt build --select orders+ --target prod |
| Pass variables | dbt run --select orders --vars '{"run_date": "2026-10-23"}' |
| Stop on the first failure | dbt build --select marts --fail-fast |
| Limit concurrency to protect the warehouse | dbt build --select marts --threads 4 |
| Check source freshness | dbt source freshness --select source:stripe |
| Test only, no model builds | dbt test --select orders |
| Look at rows a model produces, without building it | dbt show --select orders --limit 20 |
| Run ad-hoc SQL through the project's connection | dbt show --inline "select count(*) from {{ ref('orders') }}" |
| See the compiled SQL | dbt compile --select orders then open target/compiled/... |
| Run a macro (grants, cleanup) | dbt run-operation grant_select --args '{"role": "reporter"}' |
Warning
--full-refreshdrops and rebuilds incremental models and reloads seeds. On a large fact table this can take hours and leaves the table empty or locked while it runs, depending on the adapter. Confirm the time window with the data owner and run it against one model, not a folder.
dbt retry vs result selectors
dbt retry reads target/run_results.json and re-runs the failed command from the point of failure with the same flags. It only works if target/ from the failed run is still there, so in CI or orchestrators that use a fresh container, persist the artifacts or use result:error+ --state <path> against a saved copy.
Slim CI and deferral
Build only what changed in a pull request, reading unchanged parents from production:
# prod-artifacts/ contains manifest.json from the last production run
dbt build --select state:modified+ --defer --state prod-artifacts/
# Prefer the production version of unchanged nodes even if a dev copy exists
dbt build --select state:modified+ --defer --favor-state --state prod-artifacts/
# 1.6+: clone unchanged production models into the CI schema (zero-copy where the adapter supports it)
dbt clone --select state:unmodified --state prod-artifacts/
state:modified includes sub-selectors such as state:modified.body, state:modified.configs and state:modified.relation when you need to narrow it.
1.8+ and 1.9+ helpers
# 1.8+: build schema only, with zero rows, to catch SQL and contract errors cheaply
dbt build --select state:modified+ --empty
# 1.9+: reprocess a window of a microbatch incremental model
dbt run --select orders --event-time-start "2026-10-20" --event-time-end "2026-10-23"
Check dbt --version before relying on these; older versions reject the flags.
Tests and indirect selection
When you select a model, dbt also selects tests attached to it. --indirect-selection controls tests that touch several models (for example a relationships test):
| Value | Behaviour |
|---|---|
eager (default) | Run the test if any of its parents is selected |
cautious | Run only if all parents are selected |
buildable | Run if all parents are selected or are ancestors of the selection |
empty | Don't select tests indirectly |
dbt build --select orders --indirect-selection cautious
Use cautious when a partial rebuild keeps failing a relationship test against a table you didn't rebuild.
Saved selectors
Put production selections in selectors.yml so the orchestrator and on-call use the same definition:
selectors:
- name: nightly_finance
description: Nightly finance marts, without deprecated models
definition:
union:
- method: tag
value: finance
children: true
- exclude:
- method: tag
value: deprecated
dbt ls --selector nightly_finance --output name
dbt build --selector nightly_finance
Debugging flags
| Flag | Use |
|---|---|
dbt debug | Check profile, connection and dependencies |
--debug or --log-level debug | Full SQL and adapter messages on the console |
--warn-error | Treat warnings as errors (CI) |
dbt ls --output json --output-keys "name resource_type config" | Inspect node configs without opening YAML |
dbt parse | Parse only; catches YAML and Jinja errors fast |
logs/dbt.log and target/run_results.json hold the details for every run. For specific error messages, see dbt run failures.
Prevent it next time
- Tag models by schedule and owner (
tag:nightly,tag:finance) so selections stay short and readable. - Keep production selections in
selectors.yml, not hand-typed in orchestrator configs. - Save
manifest.jsonandrun_results.jsonfrom every production run; slim CI,dbt retryand incident review all depend on them. - Add
dbt lsof the planned selection to change tickets that involve--full-refresh.