$npx -y skills add flutter/agent-plugins --skill dart-resolve-package-conflictsWorkflow for fixing package version conflicts. Use this when pub get fails due to incompatible package versions.
| 1 | # Managing Dart Dependencies |
| 2 | |
| 3 | ## Contents |
| 4 | - [Core Concepts](#core-concepts) |
| 5 | - [Version Constraints](#version-constraints) |
| 6 | - [Workflow: Auditing Dependencies](#workflow-auditing-dependencies) |
| 7 | - [Workflow: Upgrading Dependencies](#workflow-upgrading-dependencies) |
| 8 | - [Workflow: Resolving Version Conflicts](#workflow-resolving-version-conflicts) |
| 9 | - [Examples](#examples) |
| 10 | |
| 11 | ## Core Concepts |
| 12 | |
| 13 | Dart enforces a strict single-version rule for dependencies: a project and all its transitive dependencies must resolve to a single, shared version of any given package. This prevents runtime type mismatches but introduces the risk of "version lock." |
| 14 | |
| 15 | To mitigate version lock, Dart relies on version constraints rather than pinned versions in the `pubspec.yaml`. The `pubspec.lock` file maintains the exact resolved versions for reproducible builds. |
| 16 | |
| 17 | Understand the output columns of `dart pub outdated`: |
| 18 | * **Current:** The version currently recorded in `pubspec.lock`. |
| 19 | * **Upgradable:** The latest version allowed by the constraints in `pubspec.yaml`. `dart pub upgrade` resolves to this. |
| 20 | * **Resolvable:** The absolute latest version that can be resolved when factoring in all other dependencies in the project. |
| 21 | * **Latest:** The latest published version of the package (excluding prereleases). |
| 22 | |
| 23 | ## Version Constraints |
| 24 | |
| 25 | * **Use Caret Syntax:** Always use caret syntax (e.g., `^1.2.3`) for dependencies in `pubspec.yaml`. This allows `pub` to select newer, non-breaking versions (up to, but not including, the next major version) during resolution. |
| 26 | * **Tighten Dev Dependencies:** Set the lower bound of `dev_dependencies` to the exact version currently used. This reduces resolution complexity and prevents older, incompatible dev tools from being selected. |
| 27 | * **Enforce Lockfiles in CI:** Use `dart pub get --enforce-lockfile` in CI/CD pipelines to ensure the exact versions tested locally are used in production. |
| 28 | |
| 29 | ## Workflow: Auditing Dependencies |
| 30 | |
| 31 | Run this workflow periodically to identify stale packages that may impact stability or performance. |
| 32 | |
| 33 | **Task Progress:** |
| 34 | - [ ] Run `dart pub outdated`. |
| 35 | - [ ] Review the **Upgradable** column to identify packages that can be updated without modifying `pubspec.yaml`. |
| 36 | - [ ] Review the **Resolvable** column to identify packages that require constraint modifications in `pubspec.yaml` to update. |
| 37 | - [ ] Identify any packages marked as retracted or discontinued. |
| 38 | |
| 39 | ## Workflow: Upgrading Dependencies |
| 40 | |
| 41 | Use conditional logic based on the audit results to upgrade dependencies. |
| 42 | |
| 43 | **Task Progress:** |
| 44 | - [ ] **If updating to "Upgradable" versions:** |
| 45 | - [ ] Run `dart pub upgrade`. |
| 46 | - [ ] Run `dart pub upgrade --tighten` to automatically update the lower bounds in `pubspec.yaml` to match the newly resolved versions. |
| 47 | - [ ] **If updating to "Resolvable" versions (Major updates):** |
| 48 | - [ ] Manually edit `pubspec.yaml` to bump the version constraint to match the "Resolvable" column (e.g., change `^0.11.0` to `^0.12.1`). |
| 49 | - [ ] Run `dart pub upgrade` to resolve the new constraints and update `pubspec.lock`. |
| 50 | - [ ] **Feedback Loop:** |
| 51 | - [ ] Run `dart analyze` -> review errors -> fix breaking API changes. |
| 52 | - [ ] Run `dart test` -> review failures -> fix regressions. |
| 53 | |
| 54 | ## Workflow: Resolving Version Conflicts |
| 55 | |
| 56 | When `pub` cannot find a set of concrete versions that satisfy all constraints, or when dealing with a retracted package version, manipulate the lockfile surgically. |
| 57 | |
| 58 | **NEVER** delete the entire `pubspec.lock` file and run `dart pub get`. This causes uncontrolled upgrades across the entire dependency graph. |
| 59 | |
| 60 | **Task Progress:** |
| 61 | - [ ] Open `pubspec.lock`. |
| 62 | - [ ] Locate the specific YAML block for the conflicting or retracted package. |
| 63 | - [ ] Delete ONLY that package's entry from the lockfile. |
| 64 | - [ ] Run `dart pub get` to fetch the newest compatible, non-retracted version for that specific package. |
| 65 | - [ ] **Feedback Loop:** |
| 66 | - [ ] Run `dart pub deps` -> verify the dependency graph resolves correctly. |
| 67 | - [ ] If resolution fails, identify the transitive dependency causing the lock, update its constraint in `pubspec.yaml`, and retry. |
| 68 | |
| 69 | ## Examples |
| 70 | |
| 71 | ### Tightening Constraints |
| 72 | When `dart pub outdated` shows a package is resolvable to a higher minor/patch version, use the `--tighten` flag to update the `pubspec.yaml` automatically. |
| 73 | |
| 74 | **Input (`pubspec.yaml`):** |
| 75 | ```yaml |
| 76 | dependencies: |
| 77 | http: ^0.13.0 |
| 78 | ``` |
| 79 | |
| 80 | **Command:** |
| 81 | ```bash |
| 82 | dart pub upgrade --tighten http |
| 83 | ``` |
| 84 | |
| 85 | **Output (`pubspec.yaml`):** |
| 86 | ```yaml |
| 87 | dependencies: |
| 88 | http: ^0.13.5 |
| 89 | ``` |
| 90 | |
| 91 | ### Surgical Lockfile Removal |
| 92 | If `package_a` is retracted or locked in a conflict, remove only its block from `pubspec.lock`. |
| 93 | |
| 94 | **Before (`pubspec.lock`):** |
| 95 | ```yaml |
| 96 | packages: |
| 97 | package_a: |
| 98 | dependency: "direct main" |
| 99 | description: |