How to migrate Dart code to Non-nullable (NNBD)?


Asked by creativecreatorormaybenot on June 02, 2020 (source).

I have a Flutter app that was written before null safety was introduced to Dart.

I heard of a Null Safety Migration Tooling and was wondering how I could use it to convert my code from pre-NNBD to Non-nullable by default.


Question answered by creativecreatorormaybenot (source).

You need at least Dart 2.9. At the time of writing, you can use, i.e. put the following SDK constraint in your pubspec.yaml:

  sdk: "> <3.0.0"

Hints (/*?*/ & /*!*/)

The /*?*/ hint means that something should explicitly be nullable.
/*!*/ means that something should be non-nullable.

You can already add these hints manually before using NNBD. Otherwise, you can add them with the tool during migration (see below).


There are ?, !, and _ edits.
? makes a type nullable after migration. _ makes it non-nullable (meaning no character is changed because non-nullable is the default).
! makes an expression non-nullable.

These edits are previewed in the migration tool.

Using the tool

Dart 2.9 comes with an nnbd_migration package.
This tool can be used to interactively convert code to NNBD.

I will cover the migration steps described in the README and try to simplify them:

  1. Go to your project in your command line and run pub get or flutter pub get when using Flutter. (Note that at the time of writing, the Flutter SDK is not yet supported)
  2. Run dart migrate. (Note that at the time of writing, I need to use --skip-pub-outdated)
  3. Wait for analysis and migration to complete and then view migration suggestions by opening the URL you see in the command line in your browser (of format http://localhost:<port>/<project path>?authToken=<token>). You should see something like this:

null safety preview

  1. Select a file to begin with. It should look something like this:

opened file

  1. View the proposed edits on the right (matching the highlighted characters):

proposed edits

  1. If you find edits that you think are not correct, find the root cause in Edit Details:


You can scroll down to trace the root expression that led to the edit proposal. When you find some wrong decision somewhere along the way, you either Add /*?*/ hint or Add /*!*/ hint as explained above (you can also add them manually in your IDE).

If an edit looks right, you do not need to do anything.

  1. You will probably need to Rerun From Sources a lot. This will apply the new hints you added and any other edits you made to the code and generate new edits. Do this until all edits look right.

    Now, you might see your hints highlighted in red, which means that the tool will remove the hints and convert them to either ?, !, or blank.

  2. You should probably save your project at this point (e.g. git commit).

    Note: at this point, your code has a bunch of added /*?*/ and /*!*/ hints and has not yet been migrated.

  3. Apply Migration: this will apply the proposed edits and remove all hints. Probably leave the migration tool open for now.

    Now, you do not have any hints in your code anymore.

  4. Test your project (pub get or flutter pub get and then run).

    If something went wrong, it is helpful to have left the migration tool open.
    Potentially, you want to revert your version to before the migration and repeat the steps.

  5. Success! Your project is now null safe 🙌🏽