## TL;DR

CI and local differ in dbt version, environment variables, or the active target, and one of those differences breaks compilation. Print `dbt --version` in CI, diff the env vars, run the exact CI command locally, fix the drift, and pin versions so it stays fixed.

## Error

```text
dbt compile error only in CI not locally
```

## Steps

1. Add `dbt --version` to the CI job and compare against your local output. Expected: you see any core or adapter version mismatch immediately.
2. Dump the relevant environment variables in CI (redact secrets) and compare with your shell. Expected: you find the missing or different variable.
3. Check which profiles target CI uses versus your local default. Expected: the target names and their configs match, or you note the intended difference.
4. Reproduce locally with the exact CI command, including flags like `--target` and `--vars`. Expected: the error reproduces, proving it is environmental.
5. Pin dbt-core and adapter versions in your requirements file and set the CI variables explicitly. Expected: CI goes green and stays green.

## When to use

- `dbt compile` (or parse) fails in CI but passes on your machine.
- The failure started after a local upgrade you did not apply to CI.

## When not to use

- The error reproduces locally (debug it locally; it is faster).
- CI fails at install time (a dependency problem, not a compile problem).

## Tool compatibility

- dbt Core 1.0 and later, all adapters, any CI provider.

## Variant phrasings

### dbt parse fails in CI only

Same diagnosis; parse is just an earlier phase of the same pipeline.

### Works on main branch CI, fails on my branch CI

Diff the branch: a new model, macro, or var on your branch is the suspect.

## Why it happens

Compilation depends on the dbt version (macro behavior changes), env vars (profiles and vars), and the target (database and schema). CI builds its environment from scratch, so any of these can differ from a long-lived local setup.

## Edge cases

- CI checking out a different ref (merge commit vs head) changes which files compile; verify the checked-out SHA.
- Caching `dbt_packages` or `target` between CI runs can poison compilation; clear caches when debugging.
- Secrets injected differently in CI (empty vs unset) change `env_var` behavior; treat empty and unset as distinct.

## Provenance

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