dbt clean Command: When and Why to Clear Compiled Artifacts
dbt clean is the smallest and least dramatic command in dbtโs CLI, and thatโs exactly why itโs worth understanding precisely โ itโs tempting to reach for it as a generic โfix weird behaviorโ reset button, but it only does one specific, narrow thing, and knowing what it doesnโt do saves time chasing the wrong fix.
What dbt clean Actually Deletes
dbt cleanBy default, this deletes the directories listed under clean-targets in dbt_project.yml โ almost always target/ (compiled SQL, run artifacts) and dbt_packages/ (installed package dependencies).
clean-targets: - "target" - "dbt_packages"Thatโs the entire scope. It does not touch anything in your actual warehouse โ no tables are dropped, no data is deleted. Itโs purely a local filesystem cleanup of generated/downloaded artifacts.
Why This Command Exists at All
Two categories of problem it genuinely solves:
Stale compiled SQL causing confusing debugging. If youโre inspecting target/compiled/ to debug a Jinja issue (the technique covered throughout this series, including in Jinja Templating) and suspect youโre looking at an old compilation rather than the current one, clearing target/ and recompiling guarantees youโre looking at fresh output.
Package installation issues. If dbt_packages/ gets into a corrupted or partially-downloaded state โ an interrupted dbt deps run, a version conflict that didnโt resolve cleanly โ clearing it and reinstalling from scratch is often faster than debugging the partial state.
dbt cleandbt depsdbt compileWhat dbt clean Does Not Fix
Itโs a common but incorrect assumption that dbt clean resets warehouse state, fixes a broken model, or clears cached query results in the warehouse itself. None of that is in scope:
| Symptom | Does dbt clean help? |
|---|---|
| Compiled SQL looks stale/wrong when debugging | Yes |
| Package installation seems corrupted | Yes |
| A model produces wrong data in the warehouse | No โ this is a data/logic problem, not a local artifact problem |
A ref() isnโt resolving correctly | No โ check the actual model file and DAG, not local caches |
| Warehouse query results seem cached/stale | No โ thatโs warehouse-level caching, unrelated to dbtโs local target/ |
Reaching for dbt clean when the actual problem is in your SQL logic or warehouse state wastes time without addressing anything.
Customizing clean-targets
Some projects generate additional local artifacts worth including in the cleanup scope โ a custom docs output directory, for instance.
clean-targets: - "target" - "dbt_packages" - "logs"Be deliberate about whatโs added here โ accidentally including a directory that contains something you didnโt mean to delete (a manually maintained local config, for instance) turns a routine cleanup into an unpleasant surprise.
dbt clean in CI Pipelines
Some CI configurations run dbt clean at the start of every job as a defensive habit, ensuring no artifacts persist between runs on a shared runner.
# Example CI step- run: dbt clean- run: dbt deps- run: dbt buildOn ephemeral CI runners that start from a fresh filesystem every time, this is usually unnecessary โ thereโs nothing stale to clean. It matters more on long-lived, shared build agents where artifacts from a previous, different branchโs run could otherwise persist and cause confusing cross-contamination between jobs.
A Realistic Scenario Where dbt clean Actually Helps
Consider switching between two feature branches locally, one that installed a newer version of dbt_utils and one still pinned to an older version. If dbt_packages/ isnโt reinstalled cleanly between the switch, you can end up with a mismatched or partially-overwritten package directory that doesnโt match either branchโs packages.yml exactly โ commands might still run, but macro behavior can be inconsistent with what either branch actually declares.
git checkout other-feature-branchdbt cleandbt depsdbt compileThis sequence guarantees the installed packages exactly match the currently checked-out branchโs declared versions, eliminating an entire category of โwhy is this macro behaving differently than I expectโ confusion that stems from a stale, partially-mismatched local package cache rather than any actual bug in your project.
Why Itโs Rarely Needed Day-to-Day
For most local development, dbt regenerates target/ fresh on every run, compile, or test invocation anyway โ you donโt need to manually clear it first for a normal compile to reflect your latest changes. The command exists for the specific edge cases above, not as a routine step in an ordinary workflow.
Common Mistakes
Running it reflexively when debugging any dbt issue. Since it only affects local artifacts, it does nothing for the much more common category of problems โ broken SQL logic, misconfigured sources, incorrect warehouse permissions.
Adding directories to clean-targets without checking whatโs actually there. A misconfigured clean-targets list can delete something genuinely useful that happened to be created in the same directory dbt expects to be disposable.
Forgetting dbt deps is needed after cleaning dbt_packages/. dbt clean removes installed packages; it doesnโt reinstall them โ a dbt deps run afterward is required before any command that depends on package macros will work again.
Summary
| Aspect | Detail |
|---|---|
| What it deletes | Local directories in clean-targets โ typically target/ and dbt_packages/ |
| What it doesnโt touch | Anything in your actual warehouse |
| Best used for | Debugging stale compiled SQL, resetting a corrupted package install |
| Follow-up needed | dbt deps to reinstall packages after cleaning them |
dbt clean is a narrow, purely local housekeeping command โ useful in the specific situations itโs designed for, and a waste of time as a generic troubleshooting reflex for anything happening in the actual warehouse.