Resolving 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.
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:
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-svgand@react-native-async-storage/async-storageeach 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 areInvariant 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. |
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:
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:
flutter pub get
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:
{
"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:
{
"dependencies": {
"react-native-svg": "15.14.0"
},
"overrides": {
"react-native-svg": "$react-native-svg"
}
}
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:
{
"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+):
{
"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:
{
"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:
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:
overrides:
"@digia-engage/core>react-native-svg": 15.14.0
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:
{
"dependencies": {
"@digia-engage/core": "^2.21.0"
},
"overrides": {
"react-native-svg": "15.14.0"
}
}
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.
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:
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
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:
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 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) oroverrides(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