## TL;DR
Pin exact versions in `packages.yml`, resolve the conflict by finding one version set all packages accept (usually by upgrading the laggard), and commit `package-lock.yml` so installs are reproducible. Version conflicts are a constraint problem; solve it with explicit pins, not hopeful ranges.

```text
dbt package dependency version conflicts
```

## Use this when
- `dbt deps` fails on version conflicts
- Two packages need different versions of a shared dependency
- You need reproducible package installs

## Not for this skill when
- You are choosing model materializations
- You are choosing snapshot strategies
- You are writing unit tests

## Steps

1. Read the actual conflict. `dbt deps` tells you who wants what:

```text
Could not find a satisfactory version from options: [...]
Required by: package-a needs dbt-utils>=1.0,[1.2; package-b needs dbt-utils]=1.2
```
Expected output: the conflicting requirements named. The fix starts from this message, not from guessing.

2. Pin everything explicitly in `packages.yml`:

```yaml
packages:
  - package: dbt-labs/dbt_utils
    version: 1.1.3
  - package: calogica/dbt_expectations
    version: 0.10.4
```
Expected output: deterministic resolution. Ranges (`>=1.0,<2.0`) feel flexible but let a fresh install resolve differently next month; exact pins do not.

3. Resolve the diamond by upgrading the laggard, not downgrading the leader:

```text
If package-a needs dbt-utils[1.2 and package-b needs ]=1.2,
check whether package-a works with 1.2 anyway (often it does;
the bound was conservative). Upgrade package-a first.
Only pin the older version if the newer genuinely breaks it.
```
Expected output: a compatible set, usually on the newer versions. Maintainers set upper bounds conservatively; the real incompatibility is rarer than the declared one.

4. Commit the lock file so every environment installs identically:

```bash
dbt deps  # generates package-lock.yml
 git add package-lock.yml packages.yml
```
Expected output: CI, colleagues, and production install the exact same package versions. Without the lock file, two installs a month apart can differ.

5. When truly stuck, vendor the conflicting package:

```text
Fork the package, relax or fix the bound, point packages.yml
at your git URL with a revision. Last resort, but it unblocks
you when upstream is slow and the bound is wrong.
```
Expected output: an unblocked pipeline with a documented fork. File the upstream issue too, so you can drop the fork later.

## Variant phrasings

### dbt deps version conflict
Read the requirements message (step 1), then pin and upgrade the laggard (steps 2-3).

### dbt package-lock.yml
Generated by `dbt deps`; commit it for reproducible installs (step 4).

### dbt packages.yml version pinning
Exact versions beat ranges for reproducibility. Ranges are for library authors; pins are for projects.

## Why it happens
dbt packages declare version bounds on shared dependencies like dbt-utils. When two packages' bounds do not overlap, no version satisfies both and `dbt deps` fails. The bounds are often stricter than reality, so the fix is usually finding the overlap the authors were too cautious to declare.

## Edge cases
- Git-based packages need a `revision` pin too; a branch name moves, a tag or SHA does not.
- Major version bumps of dbt-core itself (1.x to 2.x) invalidate many package bounds at once; upgrade packages as a batch.
- Private registry or Hub outages make `dbt deps` fail for network reasons; the error looks similar but the fix is retrying, not repinning.
- Removing a package from packages.yml does not remove it from package-lock.yml until you rerun `dbt deps`.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_y3-iE2h0zBRAZSD3yLDGLA
