## TL;DR
Work the connection chain from the inside out: dbt config, then credentials, then network, then the warehouse itself. Run `dbt debug` first, it checks every link and tells you exactly which one broke. Nine times out of ten the answer is a wrong profile target, an expired credential, or a warehouse that is asleep or unreachable, and the checklist below finds it in minutes.

```text
dbt "database error" on run: connection checklist
```

## Use this when
- every model fails with a database error before any SQL runs
- `dbt debug` reports a connection failure on one of its checks
- you just changed profiles, credentials, or environments

## Not for this skill when
- some models succeed and one fails, that is a model bug not a connection bug
- the error is permission denied on a specific schema, check grants instead
- compilation fails before dbt ever touches the database

## Steps

1. Run the built-in connection checker and read which link in the chain failed:

```shell
dbt debug
```

Expected output: a checklist with pass or fail per item, ending in "All checks passed!" when healthy. The first failing line is your culprit, start there.

2. Confirm you are pointing at the profile target you think you are, since the wrong target explains most mysteries:

```shell
dbt debug --target dev | head -25
```

Expected output: the connection details dbt resolved for that target. A surprising host, database, or schema here means profiles.yml is not what you assume it is.

3. Verify the credentials file exists and your project block looks right:

```shell
ls -la ~/.dbt/profiles.yml && grep -A6 "my_project:" ~/.dbt/profiles.yml | head -14
```

Expected output: the file exists and your project's profile block shows the expected target settings. A missing file or a typo in the project name fails everything downstream.

4. Test the network path to the warehouse host from this machine, ruling out dbt entirely:

```shell
nc -zv warehouse-host.example.com 5432
```

Expected output: a succeeded-style message. A timeout here means firewall, VPN, or DNS trouble, not a dbt problem. Replace the host and port with your warehouse's real values.

5. Check the warehouse itself is awake and accepting your role, since asleep warehouses fail the same way as broken credentials:

```sql
SELECT current_user, current_database();
```

Expected output: your dbt user and database echoed back. On Snowflake also verify the warehouse is running and your role has USAGE on it, which is the step everyone forgets.

6. Re-run the full debug after each fix until the whole chain is green, then build one small model:

```shell
dbt debug && dbt run --select stg_orders
```

Expected output: all checks pass and the model builds. Fix one layer at a time and re-verify, since multiple broken layers mask each other.

## Variant phrasings

### dbt could not connect to database
Start at step 1. dbt debug distinguishes auth failures from network failures, and those need totally different fixes, so do not guess.

### dbt debug fails on credentials
Usually an expired password, a rotated key, or an env var that is not exported in this shell. Step 2 prints the resolved target so you can see what dbt actually tried.

### dbt works locally but not in CI
CI environments often miss env vars or VPN access that your laptop has. Diff the debug output between the two machines line by line and the gap appears.

## Why it happens
dbt has to resolve four things before running any SQL: which profile target, which credentials, a network route to the host, and a live warehouse that accepts the role. A break at any layer surfaces as the same generic "database error", which is why the fix is a checklist walk from the inside out rather than one clever command.

## Edge cases
- Env var credentials like `{{ env_var('DBT_PASSWORD') }}` fail silently when the var is unset in a new shell. Export it or check your shell profile.
- Key-pair auth paths are machine-specific and break when copied between laptops and CI runners.
- Multiple profiles.yml files: dbt reads `--profiles-dir` or `~/.dbt`, and a stray file wins silently. Pass the dir explicitly in CI.
- Idle timeouts: some warehouses kill idle connections, so a long compile phase can die before the first query. It looks like a connection bug but it is a timeout.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_dKJJ9yQAAp6dKfLZZgWJjg
