Watch the video (12 min)
On this page28 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. What Pub Does
  5. 2. dart pub get
  6. 3. dart pub add
  7. 4. Transitive Dependencies
  8. 5. Seeing the Tree with dart pub deps
  9. 6. dart pub remove
  10. 7. dart pub outdated
  11. 8. dart pub upgrade
  12. 9. Path Dependencies
  13. 10. Version Solving and Conflicts
  14. 11. dependency_overrides (Use Sparingly)
  15. 12. Git Dependencies
  16. 13. The Pub Cache
  17. 14. Choosing Quality Packages on pub.dev
  18. 15. Keeping Dependencies Minimal
  19. 16. A Real-World Example
  20. Code Examples
  21. Common Beginner Mistakes
  22. Best Practices
  23. Mini Challenge
  24. Practice Questions
  25. Practice Answers
  26. Quick Revision
  27. Key Takeaways
  28. What's Next?

Lecture 105 — Dart Pub & Dependency Management

Category17 — Libraries & Packages
Lecture105 of 140
Estimated video length12 min
TargetDart 3.12.2
LevelIntermediate

Adding one package can quietly bring ten more, and packages keep releasing new versions. Pub is the tool that fetches, checks, upgrades and removes all of them for you.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every output and error message in this lecture is real. Each one was produced by running the commands and code shown. Two things will differ on your machine: package versions (packages keep releasing new ones), and the Flutter SDK line in dart pub deps, which only appears when Dart was installed together with Flutter.


Prerequisites

Students should already understand, from Lectures 101–104:

  • importing with import, as, show and hide (Lecture 101)
  • splitting code into your own library files (Lecture 102)
  • what a package is, pub.dev, and import 'package:...' (Lecture 103)
  • pubspec.yaml, version constraints such as ^1.19.1, and dev_dependencies (Lecture 104)

Connection With Previous Lectures

In Lecture 104 we wrote pubspec.yaml by hand. But a pubspec is only a wish list. Sara's program still fails until something reads that list and downloads the code:

output
Error: Couldn't resolve the package 'intl' in 'package:intl/intl.dart'.

And the questions keep coming. Which versions did we actually get? What if two packages want different versions of the same third package? How do we know when an update is out? That "something" is pub, and this lecture is about using it well.


Learning Objectives

By the end of this lecture you will be able to:

  • Run dart pub get, add, remove, deps, outdated and upgrade
  • Explain direct and transitive dependencies
  • Read a version-solving failure and fix it
  • Add path and git dependencies
  • Use dependency_overrides as a last resort
  • Explain what the pub cache is
  • Judge a package on pub.dev by likes, pub points and verified publisher
  • Keep a project's dependency list small

1. What Pub Does

Pub is Dart's package manager. You run it as dart pub <command> inside a folder that has a pubspec.yaml. It reads your constraints, picks versions that fit together, downloads them, and writes the exact versions into pubspec.lock.

Analogy — pub is a school librarian. You hand over a list ("a maths book, edition 1 or newer"). The librarian finds copies that work together, keeps them on a shared shelf, and writes down exactly which copies you borrowed.


2. dart pub get

Ali starts a project called class_report with no packages yet:

yaml
name: class_report
description: Prints a class result summary.
version: 1.0.0

environment:
  sdk: ^3.12.0
output
$ dart pub get
Resolving dependencies...
Downloading packages...
Got dependencies!

dart pub get fetches whatever the pubspec lists. If pubspec.lock already exists, it reuses the versions written there, so everyone on the team gets the same ones.


3. dart pub add

Instead of editing the pubspec by hand, let pub do it:

output
$ dart pub add collection
Resolving dependencies...
Downloading packages...
+ collection 1.19.1
Changed 1 dependency!

Pub chose the newest version, added a caret constraint to the pubspec, and ran get for you:

yaml
dependencies:
  collection: ^1.19.1

Use dart pub add --dev test for a development-only package (Lecture 104).


4. Transitive Dependencies

Ali adds one more package, http:

output
$ dart pub add http
Resolving dependencies...
Downloading packages...
+ async 2.13.1
+ http 1.6.0
+ http_parser 4.1.2
+ meta 1.19.0
+ path 1.9.1
+ source_span 1.10.2
+ string_scanner 1.4.1
+ term_glyph 1.2.2
+ typed_data 1.4.0
+ web 1.1.1
Changed 10 dependencies!

One request, ten packages. http needs async, async needs meta, and so on. Packages you list yourself are direct dependencies; packages that arrive because your packages need them are transitive dependencies.


5. Seeing the Tree with dart pub deps

dart pub deps shows who needs what. ... means "already shown above":

output
$ dart pub deps
Dart SDK 3.12.1
Flutter SDK 3.44.1
class_report 1.0.0
├── collection 1.19.1
└── http 1.6.0
    ├── async 2.13.1
    │   ├── collection...
    │   └── meta...
    ├── http_parser 4.1.2
    │   ├── collection...
    │   ├── source_span 1.10.2
    │   │   ├── collection...
    │   │   ├── path 1.9.1
    │   │   └── term_glyph 1.2.2
    │   ├── string_scanner 1.4.1
    │   │   └── source_span...
    │   └── typed_data 1.4.0
    │       └── collection...
    ├── meta 1.19.0
    └── web 1.1.1

--style=compact groups them, which is easier to read:

output
$ dart pub deps --style=compact
...
dependencies:
- collection 1.19.1
- http 1.6.0 [async http_parser meta web]

transitive dependencies:
- async 2.13.1 [collection meta]
- http_parser 4.1.2 [collection source_span string_scanner typed_data]
- meta 1.19.0
...

Notice that collection is needed by four packages but downloaded once.


6. dart pub remove

Ali doesn't need http after all:

output
$ dart pub remove http
Resolving dependencies...
Downloading packages...
These packages are no longer being depended on:
- async 2.13.1
- http 1.6.0
- http_parser 4.1.2
- meta 1.19.0
- path 1.9.1
- source_span 1.10.2
- string_scanner 1.4.1
- term_glyph 1.2.2
- typed_data 1.4.0
- web 1.1.1
Changed 10 dependencies!

Removing a direct dependency also drops every transitive one that nothing else needs.


7. dart pub outdated

Ali's pubspec now has two packages behind the times — path locked at an old 1.8.0, and intl: ^0.19.0. dart pub outdated reports it:

output
$ dart pub outdated
Showing outdated packages.
[*] indicates versions that are not the latest available.

Package Name  Current  Upgradable  Resolvable  Latest

direct dependencies:
intl          *0.19.0  *0.19.0     0.20.3      0.20.3
path          *1.8.0   1.9.1       1.9.1       1.9.1

1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.

1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
ColumnMeaning
Currentthe version in pubspec.lock now
Upgradablethe newest version your pubspec constraint allows
Resolvablethe newest version that would work if you changed the constraint
Latestthe newest version published

8. dart pub upgrade

upgrade ignores the lock file and takes the newest versions inside your constraints:

output
$ dart pub upgrade
Resolving dependencies...
Downloading packages...
  intl 0.19.0 (0.20.3 available)
> path 1.9.1 (was 1.8.0)
Changed 1 dependency!
1 package has newer versions incompatible with dependency constraints.
Try `dart pub outdated` for more information.

path moved; intl didn't, because ^0.19.0 forbids 0.20. A jump like that may contain breaking changes, so pub only makes it when you ask:

output
$ dart pub upgrade --major-versions

Changed 1 constraint in pubspec.yaml:
  intl: ^0.19.0 -> ^0.20.3
Resolving dependencies...
Downloading packages...
> intl 0.20.3 (was 0.19.0)
Changed 1 dependency!

After a major upgrade, run your program and tests before moving on.


9. Path Dependencies

A package doesn't have to live on pub.dev. Ali keeps his grading code in a local package, marks_tools, in a folder next to class_report:

dart
// marks_tools/lib/marks_tools.dart
String grade(int marks) {
  if (marks >= 80) return 'A';
  if (marks >= 60) return 'B';
  return 'C';
}

He points to it with path::

yaml
publish_to: none

dependencies:
  collection: ^1.19.1
  marks_tools:
    path: ../marks_tools
output
$ dart pub get
Resolving dependencies...
Downloading packages...
+ marks_tools 0.1.0 from path ../marks_tools
Changed 1 dependency!

Changes inside marks_tools show up the next time class_report runs — no pub get needed. publish_to: none marks the project as private; without it dart analyze warns: Publishable packages can't have 'path' dependencies.


10. Version Solving and Conflicts

Every package states which versions of its own dependencies it accepts. Pub's version solver must find one version of each package that satisfies everybody. Suppose marks_tools declares an old range:

yaml
# marks_tools/pubspec.yaml
dependencies:
  collection: ">=1.15.0 <1.18.0"

class_report asks for ^1.19.1. No version is both below 1.18.0 and at least 1.19.1:

output
$ dart pub get
Resolving dependencies...
Because every version of marks_tools from path depends on collection >=1.15.0 <1.18.0 and class_report depends on collection ^1.19.1, marks_tools from path is forbidden.
So, because class_report depends on marks_tools from path, version solving failed.


You can try the following suggestion to make the pubspec resolve:
* Consider downgrading your constraint on collection: dart pub add collection:^1.17.2

Read it like a sentence: because A needs X and B needs Y, solving failed. The real fix is to make the ranges overlap — here, widen marks_tools to collection: ^1.17.0. For a pub.dev package, try dart pub upgrade first; a newer release usually accepts newer dependencies.


11. dependency_overrides (Use Sparingly)

When you cannot change the other package, dependency_overrides forces one version for the whole project:

yaml
dependency_overrides:
  collection: ^1.19.1
output
$ dart pub get
Resolving dependencies...
Downloading packages...
! collection 1.19.1 (overridden)
Got dependencies!

The ! is a warning: pub stopped checking. marks_tools said it doesn't support collection 1.19, and you overruled it — if it breaks, that's on you. Use an override only as a short-term fix and delete it once the real one is in.


12. Git Dependencies

A package can also come straight from a git repository — useful for a fix not yet released. path: picks a folder inside the repository, and ref: a branch, tag or commit:

yaml
dependencies:
  term_glyph:
    git:
      url: https://github.com/dart-lang/tools.git
      path: pkgs/term_glyph
      ref: main
output
$ dart pub get
Resolving dependencies...
Downloading packages...
+ term_glyph 1.2.3-wip from git https://github.com/dart-lang/tools.git at a73703 in pkgs/term_glyph
Changed 1 dependency!

Pub records the exact commit (a73703...) in pubspec.lock, so a teammate gets the same code even after the branch moves on.


13. The Pub Cache

Downloaded packages don't go into your project. They go into one shared pub cache — ~/.pub-cache on macOS and Linux, %LOCALAPPDATA%\Pub\Cache on Windows — with one folder per version:

output
$ ls ~/.pub-cache/hosted/pub.dev | grep path-
path-1.8.0
path-1.8.3
path-1.9.1

Every project on your computer shares these copies, which is why the second project to use a package needs no download, and why dart pub get --offline works. Never edit files in the cache. dart pub cache repair re-downloads damaged packages; dart pub cache clean empties it.


14. Choosing Quality Packages on pub.dev

pub.dev often has several packages for the same job. Before adding one, check its page:

  • Likes — how many developers bookmarked it.
  • Pub points — an automatic score (out of 160) for documentation, formatting, static analysis and up-to-date dependencies.
  • Downloads — how widely it is used.
  • Verified publisher — a check mark showing the publisher proved who they are, such as dart.dev or google.dev.
  • Recent release and Dart 3 support — a package untouched for years may not work.

collection, path, intl and http are all published by dart.dev — safe defaults.


15. Keeping Dependencies Minimal

Every package is code you didn't write but must trust and keep updated. And each one can bring its own crowd — in a fresh project, a single dev package pulls in dozens:

output
$ dart pub add --dev test
Resolving dependencies...
Downloading packages...
+ _fe_analyzer_shared 109.0.0
+ analyzer 14.5.0
+ args 2.7.0
+ async 2.13.1
...
+ webkit_inspection_protocol 1.2.1
+ yaml 3.1.4
Changed 49 dependencies!

(43 lines left out.) That's fine for test, which you really need. But if the core libraries from Lecture 101 already do the job, skip the package — and dart pub remove anything you stop using.


16. A Real-World Example

Ali's finished class_report combines a pub.dev package and his path package:

yaml
name: class_report
description: Prints a class result summary.
version: 1.0.0
publish_to: none

environment:
  sdk: ^3.12.0

dependencies:
  collection: ^1.19.1
  marks_tools:
    path: ../marks_tools
dart
// bin/class_report.dart
import 'package:collection/collection.dart';
import 'package:marks_tools/marks_tools.dart';

void main() {
  var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 58, 'Hina': 88};
  var byGrade = groupBy(marks.keys, (name) => grade(marks[name]!));
  print(byGrade);
  print('Highest: ${marks.values.max}');
  print('Average: ${marks.values.average}');
}
output
$ dart pub get
Resolving dependencies...
Downloading packages...
Got dependencies!
$ dart pub deps --style=compact
Dart SDK 3.12.1
Flutter SDK 3.44.1
class_report 1.0.0

dependencies:
- collection 1.19.1
- marks_tools 0.1.0
$ dart run
{B: [Ali], A: [Sara, Hina], C: [Zayan]}
Highest: 95
Average: 78.25

groupBy, max and average come from collection; grade comes from marks_tools. Two direct dependencies, no transitive ones, no overrides — a clean project.


Code Examples

Examples 1–6 run inside a project called shop; Examples 7–10 run in the same project after collection and intl are added.

Example 1 — A Fresh pub get

output
$ dart pub get
Resolving dependencies...
Downloading packages...
Got dependencies!

Example 2 — Adding with a Constraint

output
$ dart pub add 'path:^1.9.0'
Resolving dependencies...
Downloading packages...
+ path 1.9.1
Changed 1 dependency!
dart
import 'package:path/path.dart' as p;

void main() {
  print(p.join('reports', '2026', 'marks.txt'));
  print(p.extension('marks.txt'));
  print(p.basenameWithoutExtension('reports/ali.txt'));
}
output
reports/2026/marks.txt
.txt
ali

The quotes keep your terminal from treating ^ as a special character.

Example 3 — Two Packages at Once

output
$ dart pub add collection intl
Resolving dependencies...
Downloading packages...
+ clock 1.1.3
  collection 1.19.1 (from transitive dependency to direct dependency)
+ intl 0.20.3
Changed 3 dependencies!

shop already had test as a dev dependency, which had brought collection in as a transitive dependency; now it is direct.

Example 4 — Deps Without Dev Packages

output
$ dart pub deps --style=compact --no-dev
Dart SDK 3.12.1
Flutter SDK 3.44.1
shop 0.0.0

dependencies:
- collection 1.19.1
- intl 0.20.3 [clock meta path]
- path 1.9.1

transitive dependencies:
- clock 1.1.3
- meta 1.19.0

Example 5 — Working Offline

output
$ dart pub get --offline
Resolving dependencies...
Downloading packages...
Got dependencies!

Everything came from the pub cache.

Example 6 — Upgrading One Package

output
$ dart pub upgrade collection
Resolving dependencies...
Downloading packages...
No dependencies changed.

Already the newest allowed version — nothing to do.

Example 7 — Student Marks

dart
import 'package:collection/collection.dart';

void main() {
  var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 58, 'Hina': 88};
  print('Highest: ${marks.values.max}');
  print('Average: ${marks.values.average}');
  var ranked = marks.keys.sortedBy((name) => -marks[name]!);
  print('Ranking: $ranked');
}
output
Highest: 95
Average: 78.25
Ranking: [Sara, Hina, Ali, Zayan]

.max comes from collection — no reduce needed. Sorting by the negative mark puts the highest first.

Example 8 — Shopping Total

dart
import 'package:collection/collection.dart';
import 'package:intl/intl.dart';

void main() {
  var cart = {'Notebook': 500, 'Pen': 50, 'Bag': 1500, 'Laptop': 85000};
  var total = cart.values.sum;
  var format = NumberFormat('#,###');
  print('Items: ${cart.length}');
  print('Total: Rs ${format.format(total)}');
}
output
Items: 4
Total: Rs 87,050

Example 9 — Bank Balance

dart
import 'package:intl/intl.dart';

void main() {
  var balance = 1250000.5;
  var money = NumberFormat.currency(symbol: 'Rs ', decimalDigits: 2);
  print("Sara's balance: ${money.format(balance)}");
}
output
Sara's balance: Rs 1,250,000.50

Example 10 — A Week of Temperatures

dart
import 'package:collection/collection.dart';

void main() {
  var week = [29.5, 31.0, 30.5, 32.0, 28.0, 30.0, 33.5];
  print('Hottest: ${week.max}');
  print('Coldest: ${week.min}');
  print('Average: ${week.average.toStringAsFixed(1)}');
  var firstHot = week.firstWhereOrNull((t) => t > 35);
  print('First day above 35: ${firstHot ?? 'none'}');
}
output
Hottest: 33.5
Coldest: 28.0
Average: 30.6
First day above 35: none

firstWhereOrNull returns null instead of throwing, so ?? can supply a default.


Common Beginner Mistakes

1. Importing a package you never added

dart
// import 'package:intl/intl.dart'; // ✗ intl is not in pubspec.yaml
output
Error: Couldn't resolve the package 'intl' in 'package:intl/intl.dart'.

Run dart pub add intl first.

2. Running pub outside the project folder

Pub answers: Found no `pubspec.yaml` file in `<your folder>` or parent directories.

cd into the folder that holds pubspec.yaml.

3. Misspelling a package name

output
$ dart pub add colection
Because class_report depends on colection any which doesn't exist (could not find package colection at https://pub.dev), version solving failed.

Copy the name from the package's pub.dev page.

4. Expecting dart pub upgrade to cross a major version

upgrade stays inside your constraints, so ^0.19.0 never becomes 0.20. Use dart pub upgrade --major-versions or edit the constraint.

5. Leaving an override in place

A forgotten dependency_overrides entry hides future conflicts. Each dart pub get prints (overridden) — treat it as a to-do item.

6. Editing files in the pub cache

A change in ~/.pub-cache affects every project and is lost on dart pub cache repair. If you need to change a package, copy it and use a path dependency.


Best Practices

  • Use dart pub add and dart pub remove rather than hand-editing dependency lists.
  • Commit pubspec.lock for apps, so everyone runs the same versions.
  • Run dart pub outdated regularly; upgrade in small steps and test after each.
  • Fix conflicts by making ranges overlap; use dependency_overrides only briefly.
  • Add publish_to: none to projects with path dependencies.
  • Prefer packages with a verified publisher, high pub points and a recent release.
  • Add a package only when the core libraries can't do the job.

Mini Challenge

Zayan's shop project needs sorted prices and a formatted total. Add both packages with one command, then print the prices cheapest first and their total.

Your program should print exactly:

output
Cheapest first: [50, 500, 1500, 85000]
Total: Rs 87,050

Try it yourself before opening the solution.

Show solution
output
$ dart pub add collection intl
dart
import 'package:collection/collection.dart';
import 'package:intl/intl.dart';

void main() {
  var prices = [1500, 50, 85000, 500];
  var format = NumberFormat('#,###');
  print('Cheapest first: ${prices.sorted((a, b) => a.compareTo(b))}');
  print('Total: Rs ${format.format(prices.sum)}');
}
output
Cheapest first: [50, 500, 1500, 85000]
Total: Rs 87,050

How it works

  1. sorted from collection returns a new sorted list and leaves prices unchanged.
  2. sum adds the list; NumberFormat adds the thousands separator.

Practice Questions

Work through these in order — they run from beginner to application to challenge.

Beginner

  1. Which command downloads the packages listed in pubspec.yaml?

  2. Add the path package and print p.join('marks', 'ali.txt').

  3. In this output, which packages are transitive dependencies?

    output
    dependencies:
    - intl 0.20.3 [clock meta path]
    - path 1.9.1
    
    transitive dependencies:
    - clock 1.1.3
    - meta 1.19.0

Application

  1. Write the pubspec lines for a path dependency on a folder ../bank_tools.

  2. Using the dart pub outdated table in Step 7, which command updates path, and which updates intl?

  3. With collection, print the sum and average of [40, 75, 90, 65].

  4. This program fails with Couldn't resolve the package 'intl'. Fix it so it prints 2,050.

    dart
    import 'package:intl/intl.dart';
    
    void main() {
      print(NumberFormat('#,###').format(2050));
    }
  5. Write a git dependency on term_glyph, found in the pkgs/term_glyph folder of https://github.com/dart-lang/tools.git, on the main branch.

Challenge

  1. Explain this message, then give the proper fix and the last-resort fix:

    output
    Because every version of marks_tools from path depends on collection >=1.15.0 <1.18.0 and class_report depends on collection ^1.19.1, marks_tools from path is forbidden.
  2. Using groupBy from collection, group [29.5, 31.0, 30.5, 28.0, 33.5] into 'hot' (30 or more) and 'mild', and print the map.


Practice Answers

Question 1 — Solution

output
$ dart pub get
Resolving dependencies...
Downloading packages...
Got dependencies!

Question 2 — Solution

output
$ dart pub add path
dart
import 'package:path/path.dart' as p;

void main() {
  print(p.join('marks', 'ali.txt'));
}
output
marks/ali.txt

On Windows p.join uses a backslash: marks\ali.txt.

Question 3 — Solution

clock and meta. They arrived because intl needs them. (path is direct here, even though intl needs it too.)

Question 4 — Solution

yaml
publish_to: none

dependencies:
  bank_tools:
    path: ../bank_tools

Question 5 — Solution

path is upgradable inside its constraint, so dart pub upgrade updates it. intl needs a new constraint, so use dart pub upgrade --major-versions (or change it to ^0.20.3).

Question 6 — Solution

dart
import 'package:collection/collection.dart';

void main() {
  var marks = [40, 75, 90, 65];
  print('Sum: ${marks.sum}');
  print('Average: ${marks.average}');
}
output
Sum: 270
Average: 67.5

Question 7 — Solution

The code is fine; the package is missing. Run:

output
$ dart pub add intl

Then dart run prints:

output
2,050

Question 8 — Solution

yaml
dependencies:
  term_glyph:
    git:
      url: https://github.com/dart-lang/tools.git
      path: pkgs/term_glyph
      ref: main

Question 9 — Solution

marks_tools accepts only collection below 1.18.0; class_report needs 1.19.1 or newer. No version satisfies both, so version solving fails. The proper fix is to widen marks_tools to collection: ^1.17.0. The last resort is an override in class_report:

yaml
dependency_overrides:
  collection: ^1.19.1

Question 10 — Solution

dart
import 'package:collection/collection.dart';

void main() {
  var temps = [29.5, 31.0, 30.5, 28.0, 33.5];
  var groups = groupBy(temps, (t) => t >= 30 ? 'hot' : 'mild');
  print(groups);
}
output
{mild: [29.5, 28.0], hot: [31.0, 30.5, 33.5]}

Quick Revision

  1. What does dart pub get do when pubspec.lock already exists?
  2. What is a transitive dependency?
  3. Which command shows the dependency tree?
  4. What do the Upgradable and Resolvable columns of dart pub outdated mean?
  5. Why doesn't dart pub upgrade move ^0.19.0 to 0.20.3?
  6. When does version solving fail?
  7. What does the ! before (overridden) warn you about?
  8. Where are downloaded packages stored?
  9. Name three signs of a quality package on pub.dev.

Key Takeaways

  • Pub fetches packages, solves versions and records them in pubspec.lock.
  • get fetches, add/remove edit the pubspec, deps shows the tree, outdated reports updates, upgrade applies them.
  • Packages you list are direct; packages they need are transitive.
  • upgrade stays inside your constraints; --major-versions changes them.
  • Version solving fails when no single version satisfies every constraint — make the ranges overlap.
  • path: and git: dependencies load packages from a folder or a repository.
  • dependency_overrides switches off a safety check; use it briefly, if at all.
  • All projects share one pub cache; never edit it.
  • Choose packages by pub points, likes, downloads and a verified publisher — and add as few as you can.

What's Next?

Lecture 106 — File Handling. That closes Category 17: you can now import libraries, build your own, and manage packages. Next we start Category 18 and let programs save data — reading and writing files with dart:io, so Ali's class report can live on disk instead of vanishing when the program ends.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.