skip to content

In a Dart or Flutter pubspec.yaml, what does `dependency_overrides` do, why do overrides in a published package have no effect on its users, and what are the risks?

level: seniorimportance: should knowfreq 30%

answer

  1. replaces every reference in the graph
  2. version or local path
  3. only the root pubspec counts
  4. bypasses declared compatibility
  5. dart pub add override:

basics

~20 s

dependency_overrides forces one version or source of a package for every reference in the graph, ignoring other packages' constraints. Only the root package's overrides are honoured, so a published package's overrides do nothing for users, and forcing an untested version can break at run time.

solid answer

~40 s

`dependency_overrides` replaces **all** references to a package during resolution, with a version (`transmogrify: '3.2.1'`) or another source such as a local `path:` to a patched copy. Pub then ignores what other packages' constraints say about it. Two uses are common: testing a local fix to a package deep in the graph without editing every intermediate pubspec, and unblocking a solve while waiting for an upstream constraint bump. **Only the root package's overrides count**; overrides inside dependencies are ignored, so a published package's overrides never reach its users. The risk is that you override the compatibility promise: a version outside a package's declared range can compile and still fail at run time. Treat overrides as temporary and documented. `dart pub add override:foo:1.0.0` writes one.

code

yaml · 16 lines
yaml
name: weather_app
publish_to: 'none'

environment:
  sdk: ^3.13.0

dependencies:
  http: ^1.6.0
  legacy_analytics: ^2.4.0   # still caps http below 1.6

dependency_overrides:
  # TEMP: remove when legacy_analytics widens its http constraint.
  http: 1.6.0
  # Local patch used by every package in the graph:
  transmogrify:
    path: ../transmogrify_patch/

go deeper

for a junior

Know that dependency_overrides forces a version or source for a package and is meant as a temporary fix.

for a middle

Explain that overrides apply to every reference in the graph but only in the root pubspec, and what that means for published packages.

for a senior

Use overrides to test deep patches or unblock a solve, with a documented exit, and verify the overridden paths at run time.

for a principal

Set rules for when overrides may be committed, who owns removing them, and how upstream constraint fixes are chased.

## What an override does Normally pub's solver must satisfy every constraint in the graph: yours and those declared by each package you depend on. `dependency_overrides` suspends that for one package. Whatever you write there is used **everywhere** the package appears, and every other constraint on it is ignored. Two forms are common: - **A version.** `transmogrify: '3.2.1'` forces that exact version even where a dependency declared `^2.0.0`. - **A source.** `transmogrify: {path: ../transmogrify_patch/}` swaps in a local copy, or a `git:` fork, for every user of the package in the graph. After `dart pub get` or `dart pub upgrade`, the lockfile records the overridden version or source. ## When it is the right tool 1. **Testing a patch deep in the graph.** You are fixing `transmogrify`, which three of your dependencies use. One override with a `path:` makes all of them use your local copy, without cloning and editing their pubspecs. 2. **Unblocking a solve.** A dependency still caps a shared package below a version you need, and upstream has a fix pending. An override lets you move on while you wait. 3. **Reproducing a bug** against a specific version of a transitive package. ## Only the root pubspec counts Overrides are honoured **only in the package being resolved**, the root. Overrides declared inside depended-on packages are ignored. dart.dev draws the conclusion for publishers: if you publish a package, its `dependency_overrides` are ignored by all of its users. An override therefore can never be a fix you ship to consumers; the real fix is a constraint change in the package that caused the conflict. | Where the override is written | Effect | |---|---| | your app's pubspec (root) | applies to the whole graph | | a package your app depends on | ignored during your resolution | | a published package on pub.dev | ignored by every user of that package | ## The risks An override deliberately bypasses the compatibility information the ecosystem runs on, so: - a forced version **outside a package's declared range** may compile and fail at run time where an API changed behaviour; - a local path copy with unexpected changes can alter behaviour for every package that uses it; - a forgotten override silently **pins** a package, so later upgrades never reach it and security fixes are missed. Good practice: - add a comment naming the reason and the upstream issue or release you are waiting for; - remove the override as soon as upstream constraints allow it, and re-run the tests; - never rely on an override in a package you publish, since consumers ignore it. ## Adding one from the CLI `dart pub add override:foo:1.0.0` writes `foo: 1.0.0` under `dependency_overrides`, and the same `override:` prefix accepts a package descriptor, so `dart pub add 'override:foo:{path: ../foo}'` points it at a local copy. ## A worked conflict Your app needs `http: ^1.6.0`, but an older analytics package in your graph declares `http: '>=1.2.0 <1.5.0'`. The solver cannot satisfy both. An override on `http` resolves the graph, at the price that the analytics package now runs against an `http` version it never declared support for. Run its code paths in tests, and file or track the upstream constraint fix.

  • A Dart package author adds `dependency_overrides` to fix a conflict, then publishes. Why do users still hit the conflict?
    Pub honours overrides only in the root package being resolved. In a user's app, the published package is a dependency, so its overrides are ignored. The fix has to be a real constraint change, either in this package's dependencies section or upstream.
  • In a Flutter app, how do you know an override is still needed?
    Remove it and run `dart pub get`; if resolution succeeds, it was no longer needed. If it fails, the solver's message names the conflicting constraints, telling you which upstream package still has to widen its range.

saying these in an interview costs you the question

  • Overrides in a dependency's pubspec apply to its consumers
  • An override only affects the direct dependency, not transitive uses
  • If the solve succeeds with an override, the combination is safe
  • dependency_overrides is the standard fix to ship in a package
  • Overrides only accept versions, never paths or git sources