This page lists diagnostic messages produced by the Dart analyzer, with details about what those messages mean and how you can fix your code. For more information about the analyzer, see Customizing static analysis.
This page uses the following terms.
A type is potentially non-nullable if it‘s either explicitly non-nullable or if it’s a type parameter. The latter case is included because the actual runtime type might be non-nullable.
The analyzer produces the following diagnostics for code that doesn't conform to the language specification or that might work in unexpected ways.
This literal contains both ‘Map’ and ‘Iterable’ spreads, which makes it impossible to determine whether the literal is a map or a set.
Because map and set literals use the same delimiters ({
and }
), the analyzer looks at the type arguments and the elements to determine which kind of literal you meant. When there are no type arguments and all of the elements are spread elements (which are allowed in both kinds of literals), then the analyzer uses the types of the expressions that are being spread. If all of the expressions have the type Iterable
, then it‘s a set literal; if they all have the type Map
, then it’s a map literal.
The analyzer produces this diagnostic when some of the expressions being spread have the type Iterable
and others have the type Map
, making it impossible for the analyzer to determine whether you are writing a map literal or a set literal.
The following code produces this diagnostic:
union(Map<String, String> a, List<String> b, Map<String, String> c) => {...a, ...b, ...c};
The list b
can only be spread into a set, and the maps a
and c
can only be spread into a map, and the literal can't be both.
There are two common ways to fix this problem. The first is to remove all of the spread elements of one kind or the other, so that the elements are consistent. In this case, that likely means removing the list (and deciding what to do about the now unused parameter):
union(Map<String, String> a, List<String> b, Map<String, String> c) => {...a, ...c};
The second fix is to change the elements of one kind into elements that are consistent with the other elements. For example, you could add the elements of the list as keys that map to themselves:
union(Map<String, String> a, List<String> b, Map<String, String> c) => {...a, for (String s in b) s: s, ...c};
This literal must be either a map or a set, but the elements don't have enough type information for type inference to work.
Because map and set literals use the same delimiters (‘{
and }
), the analyzer looks at the type arguments and the elements to determine which kind of literal you meant. When there are no type arguments and all of the elements are spread elements (which are allowed in both kinds of literals) then the analyzer uses the types of the expressions that are being spread to decide. If all of the expressions have the type Iterable
, then it‘s a set literal, if they all have the type Map
, then it’s a map literal.
This diagnostic is produced when none of the expressions being spread has a type that allows the analyzer to decide whether you were writing a map literal or a set literal.
The following code produces this diagnostic:
union(a, b) => !{...a, ...b}!;
The problem occurs because there are no type arguments, and there is no information about the type of either a
or b
.
There are three common ways to fix this problem. The first is to add type arguments to the literal. For example, if the literal is intended to be a map literal, you might write something like this:
union(a, b) => <String, String>{...a, ...b};
The second fix is to add type information so that the expressions have either the type Iterable
or the type Map
. You could add an explicit cast or, in this case, add types to the declarations of the two parameters:
union(List<int> a, List<int> b) => {...a, ...b};
The third fix is to add context information. In this case, that means adding a return type to the function:
Set<String> union(a, b) => {...a, ...b};
In other cases, you might add a type somewhere else. For example, say the original code looks like this:
union(a, b) { var x = {...a, ...b}; return x; }
You might add a type annotation on x
, like this:
union(a, b) { Map<String, String> x = {...a, ...b}; return x; }
Required named parameters can't have a default value.
The analyzer produces this diagnostic when a named parameter has both the required
modifier and a default value. If the parameter is required, then a value for the parameter is always provided at the call sites, so the default value can never be used.
The following code generates this diagnostic:
void log({required String !message! = 'no message'}) {}
If the parameter is really required, then remove the default value:
void log({required String message}) {}
If the parameter isn't always required, then remove the required
modifier:
void log({String message = 'no message'}) {}
‘{0}’ is deprecated and shouldn't be used.
The analyzer produces this diagnostic when a deprecated library or class member is used in a different package.
If the method m
in the class C
is annotated with @deprecated
, then the following code produces this diagnostic:
void f(C c) { c.!m!(); }
The documentation for declarations that are annotated with @deprecated
should have documentation to indicate what code to use in place of the deprecated code.
Expressions can't be used in a map literal.
The analyzer produces this diagnostic when the analyzer finds an expression, rather than a map entry, in what appears to be a map literal.
The following code generates this diagnostic:
var map = <String, int>{'a': 0, 'b': 1, !'c'!};
If the expression is intended to compute either a key or a value in an entry, fix the issue by completing the code:
var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
Only const constructors can have the @literal
annotation.
The meaning of the @literal
annotation is only defined when it's applied to a const constructor.
The following code produces this diagnostic:
!@literal! var x;
Remove the annotation:
var x;
The parameter ‘{0}’ can't have a value of ‘null’ because of its type, so it must either be a required parameter or have a default value.
The analyzer produces this diagnostic when an optional parameter doesn‘t have a default value, but has a potentially non-nullable type. Optional parameters that have no explicit default value have an implicit default value of null
. If the type of the parameter doesn’t allow the parameter to have a value of null, then the implicit default value is not valid.
The following code generates this diagnostic:
void log({String !message!}) {}
If the parameter can have the value null
, then add a question mark after the type annotation:
void log({String? message}) {}
If the parameter can't be null, then either provide a default value:
void log({String message = ''}) {}
or add the required
modifier to the parameter:
void log({required String message}) {}
Spread elements in list or set literals must implement ‘Iterable’.
The analyzer produces this diagnostic when the static type of the expression of a spread element that appears in either a list literal or a set literal doesn't implement the type Iterable
.
The following code generates this diagnostic:
var m = <String, int>{'a': 0, 'b': 1}; var s = <String>{...m};
The most common fix is to replace the expression with one that produces an iterable object:
var m = <String, int>{'a': 0, 'b': 1}; var s = <String>{...m.keys};
A class can't extend a nullable type.
The analyzer produces this diagnostic when a class declaration uses an extends clause to specify a superclass, and the type that's specified is a nullable type.
The reason the supertype is a type rather than a class name is to allow you to control the signatures of the members to be inherited from the supertype, such as by specifying type arguments. However, the nullability of a type doesn‘t change the signatures of any members, so there isn’t any reason to allow the nullability to be specified when used in the extends clause.
The following code generates this diagnostic:
class Invalid extends !Duration?! {}
The most common fix is to remove the question mark:
class Invalid extends Duration {}
Set literals weren't supported until version 2.2, but this code must be able to run on earlier versions.
The analyzer produces this diagnostic when a set literal is found in code that has an SDK constraint whose lower bound is less than 2.2. Set literals were not supported in earlier versions, so this code won't be able to run against earlier versions of the SDK.
In a package that defines SDK constraints in the pubspec.yaml
file that have a lower bound that's less than 2.2:
environment: sdk: '>=2.1.0 <2.4.0'
The following code generates this diagnostic:
var s = !<int>{}!;
If you don't need to support older versions of the SDK, then you can increase the SDK constraint to allow the syntax to be used:
environment: sdk: '>=2.2.0 <2.4.0'
If you do need to support older versions of the SDK, then replace the set literal with code that creates the set without the use of a literal:
var s = new Set<int>();