# Resolving Dependency Conflicts

URL: https://www.digia.tech/docs/developer/reference/dependency-conflicts

The Digia Engage SDK depends on common packages your app very likely already uses — image caching, storage, device info, SVG rendering. When your app pins a different version than the SDK asks for, the install either **fails outright** or **quietly installs two copies** .

Both are fixed the same way: pick one version and force it with an override.

info
This is a normal, expected part of adding any SDK to a mature app. An override is not a workaround — it is the supported mechanism both ecosystems provide for exactly this.

## What goes wrong

The symptom differs by ecosystem, which is why the fix looks different.

- Flutter - React Native
Pub allows **only one version** of a package across your whole dependency graph. If your app and `digia_engage` ask for incompatible ranges, `flutter pub get` refuses to resolve:
```text
Because digia_engage >=1.17.0 depends on device_info_plus ^10.1.0 and
my_app depends on device_info_plus ^12.0.0, version solving failed.
```

This is a **hard failure at install time** — loud, and it blocks the build until you resolve it. Nothing is silently duplicated.

npm and friends happily install **two copies** at different paths in `node_modules` . Nothing fails at install time, and the damage shows up later:
- **Native modules break.**`react-native-svg` and `@react-native-async-storage/async-storage` each ship native code. Autolinking registers **one** native implementation, but two JS copies may be loaded — so one of them talks to a native module that isn't there. Typical symptoms are `Invariant Violation` , a null native module, or views that render blank.
- **Bundle size grows** for every duplicated package.
This is a **silent failure** , which makes it the more dangerous of the two.

### Packages most likely to collide

| Stack | Digia depends on | Why it collides | **Flutter** | `device_info_plus` , `package_info_plus` , `share_plus` | The `_plus` family bumps major versions often | **Flutter** | `shared_preferences` , `path_provider` , `url_launcher` , `dio` , `video_player` | Near-universal in production apps | **React Native** | `react-native-svg` , `@react-native-async-storage/async-storage` | Native modules — duplication actually breaks them | **React Native** | `@floating-ui/core` , `react-native-uuid` | Pure JS; duplication costs bundle size, not correctness 

## Which version to pick

**Use the version your app already depends on** , provided it still satisfies the SDK's constraint.

That is the whole point of the override: collapse two versions into one, and the app's version is almost always the right survivor. Your app's code is far larger than the SDK's usage of that package, your team has already tested against it, and other packages in your tree are likely built against it too.

Before you commit to it, check the direction of the mismatch:

| Situation | What to do | App's version is **newer** and API-compatible | Override to the app's version. This is the common case. | App's version is **older** than the SDK's floor | Prefer upgrading your app's dependency. Forcing the older one can break the SDK at runtime — it may call an API that version doesn't have. | Versions differ by a **major** in either direction | Read that package's changelog before forcing either. A major bump means a breaking change that one side has not been tested against. 

warning
An override **bypasses the resolver's safety check** . You are telling the tool "trust me, these are compatible." Nothing verifies that claim, so test the affected features after applying one — for the SDK side that means checking that campaigns still render.

## Flutter — `dependency_overrides`

Add a `dependency_overrides` section to your app's `pubspec.yaml` , alongside `dependencies` :
```yaml
dependencies:
  flutter:
    sdk: flutter
  digia_engage: ^1.17.1
  device_info_plus: ^12.0.0   # the version your app uses

dependency_overrides:
  device_info_plus: ^12.0.0   # force this one everywhere, including inside digia_engage
```

Then:
```bash
flutter pub get
```

warning
**`dependency_overrides` only works in the root package** — the app you actually build. Pub ignores the `dependency_overrides` of any package you depend on. If you maintain an internal package that wraps Digia, the override must go in the **app's**`pubspec.yaml` , not your wrapper's.

You can also pin an exact version ( `device_info_plus: 12.0.1` ) or point at a local path or Git ref while testing a fix.

## React Native — overrides by package manager

Every package manager solves this, but the field name and file location differ. Use the one matching the lockfile in your repo.
- npm - Yarn - pnpm - Bun
Add an `overrides` block to your app's `package.json` :
```json
{
  "dependencies": {
    "@digia-engage/core": "^2.21.0",
    "react-native-svg": "15.14.0"
  },
  "overrides": {
    "react-native-svg": "15.14.0"
  }
}
```

Because "use the version my app already depends on" is the normal intent, npm has shorthand for it — `$` references your own direct dependency, so the two can never drift apart:
```json
{
  "dependencies": {
    "react-native-svg": "15.14.0"
  },
  "overrides": {
    "react-native-svg": "$react-native-svg"
  }
}
```

info
npm refuses an override for a package you directly depend on unless both specs match **exactly** . The `$` form sidesteps that entirely and is the recommended way to dedupe.

To restrict the override to Digia's subtree only, rather than your whole project:
```json
{
  "overrides": {
    "@digia-engage/core": {
      "react-native-svg": "15.14.0"
    }
  }
}
```

Yarn uses `resolutions` , in your app's `package.json` . This works in both Yarn Classic (1.x) and Yarn Berry (2+):
```json
{
  "dependencies": {
    "@digia-engage/core": "^2.21.0",
    "react-native-svg": "15.14.0"
  },
  "resolutions": {
    "react-native-svg": "15.14.0"
  }
}
```

Glob patterns let you scope the override:
```json
{
  "resolutions": {
    "**/react-native-svg": "15.14.0",
    "@digia-engage/core/react-native-svg": "15.14.0"
  }
}
```

Put `overrides` in **`pnpm-workspace.yaml`** at the root of your project:
```yaml
overrides:
  react-native-svg: 15.14.0
  "@react-native-async-storage/async-storage": 2.1.2
```

Parent selectors scope an override to one package's subtree:
```yaml
overrides:
  "@digia-engage/core>react-native-svg": 15.14.0
```

warning
**pnpm 11 silently ignores `pnpm.overrides` in `package.json`** — no warning, no error, no deprecation notice. If you are upgrading from pnpm 10 and your overrides simply stop taking effect, this is why. Move them to `pnpm-workspace.yaml` .

Bun reads **both** npm's `overrides` and Yarn's `resolutions` from your app's `package.json` — use whichever your team already knows:
```json
{
  "dependencies": {
    "@digia-engage/core": "^2.21.0"
  },
  "overrides": {
    "react-native-svg": "15.14.0"
  }
}
```

warning
Bun supports **top-level overrides only** — the nested form that scopes an override to one parent package is not supported. An override in Bun always applies to your entire dependency tree.

warning
Every one of these is read from the **root**`package.json` (or `pnpm-workspace.yaml` ) only. An override declared inside a workspace package or an installed dependency is ignored.

### Reinstall cleanly

Overrides change how the tree resolves, so a stale lockfile or `node_modules` will hide the fix:
```bash
rm -rf node_modules
npm install          # or: yarn install / pnpm install / bun install

cd ios && pod install && cd ..
```

`pod install` matters whenever the duplicated package ships native code — the CocoaPods lockfile still references the old resolution until you re-run it.

## Confirm the duplicate is gone

- Flutter - React Native

```bash
flutter pub deps --style=compact | grep device_info_plus
```

`flutter pub get` succeeding is itself strong evidence — pub cannot resolve at all while a genuine conflict remains.

Ask your package manager who depends on the package. You want exactly **one** version in the output:
```bash
npm ls react-native-svg
yarn why react-native-svg
pnpm why react-native-svg
bun pm ls --all | grep react-native-svg
```

A healthy result lists a single version, even if several packages depend on it. Two version numbers means the override has not taken effect — check that you edited the root manifest and did a clean reinstall.

Then run the app and confirm a campaign still renders. An override silences the resolver, so a real runtime check is the only thing that proves the two versions were actually compatible.

## When an override is the wrong fix

- **The SDK needs a newer major than your app can move to.** Forcing the old version will fail at runtime instead of install time. Upgrade the app's dependency, or [contact support](mailto:engg@digia.tech) so we can check whether the constraint can be widened.
- **Two packages need genuinely incompatible majors.** No single version satisfies both; one of them has to move.
- **You are shipping a library, not an app.** Your `dependency_overrides` (Flutter) or `overrides` (npm) are ignored by your consumers. Widen your own constraints instead, so your users can resolve it in their app.

## Related pages

- Overview — installing the SDK
- SDK Debug Settings — inspecting SDK state on-device
