## TL;DR
dbt reads environment variables only through the env_var() Jinja function, and only at parse time. Put secrets in profiles.yml via env_var, keep warehouse and schema names per target, and never commit a real value. If dbt says the variable is not found, the process that launched dbt did not have it set.

```text
dbt environment variables
```

## Use this when
- You need database credentials or config in dbt without committing them.
- The same project must run against dev, staging, and prod targets.
- dbt fails with env_var not found and you know the variable exists somewhere.

## Not for this skill when
- You want variables scoped to one dbt Cloud job run. Use job environment variables there.
- The value changes per model run. env_var is parse-time only; it cannot vary mid-run.

## Steps
1. Reference the variable as {{ env_var('MY_VAR') }} in profiles.yml or model config, with a default where safe: {{ env_var('MY_VAR', 'fallback') }}. Note dbt parses without a not-found error. Verify: the reference syntax is correct
2. Export the variable in the shell or CI environment that launches dbt, then run dbt debug. Note the connection succeeds. Verify: the launching process actually carries the variable
3. Move any committed real values out of the repo and into the environment or a secrets manager. Note git history no longer holds a usable credential. Verify: no secret lives in version control
4. Define per-target values in profiles.yml so dev and prod resolve differently. Note dbt --target prod picks up the prod value. Verify: environments stay separated
5. In dbt Cloud, set the same names under the environment settings and redeploy. Note the Cloud run resolves them identically to local. Verify: local and Cloud agree

## Variant phrasings
### dbt env_var not found
The error phrasing when the variable is missing at parse time.
### dbt use env variable in profiles.yml
The setup-shaped search.

Compatibility: dbt Core 1.x and dbt Cloud. env_var behavior is stable across versions; dbt Cloud additionally injects DBT_ENV_SECRET_* variables.

## Why it happens
dbt compiles Jinja before it talks to the warehouse, so env_var resolves once at parse time from the launching process environment. That single fact explains most confusion: variables set inside a model, set after dbt starts, or set in a different shell are invisible to it. The function is deliberately narrow so that compiled artifacts stay deterministic for a given environment.

## Edge cases / pitfalls
- env_var with no default raises at parse time and fails the whole run, even for unrelated models. Defaults are cheap insurance.
- CI systems sometimes mask but still pass secrets; dbt debug prints target config, so run it with --no-partial-parse in shared logs to avoid leaking values.
- On Windows, variable names are case-insensitive but dbt looks them up case-sensitively. Match the case exactly.
- dbt Cloud's git provider settings can override environment variables silently. Check both places when a value looks wrong.

## Provenance

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