AppTech Logo
Fixing "Type 'Fragment' not found" and "DiagnosticType isn't defined" in Flutter's build_runner

Fixing "Type 'Fragment' not found" and "DiagnosticType isn't defined" in Flutter's build_runner

Flutter
IA
Irfan Ahmad
Flutter & iOS Developer
August 24, 20263 min read

The problem

I was running code generation on one of my Flutter apps, the way I do dozens of times a day:

Bash
1dart run build_runner build --delete-conflicting-outputs
2
3Instead of the usual "Succeeded" message, I got dozens of lines like this:
4
5Error: Type 'Fragment' not found.
6  Future<AstNode?> astNodeFor(Fragment fragment, {bool resolve = false});
7                              ^^^^^^^^
8
9Error: The getter 'firstFragment' isn't defined for the type 'Element'.
10    final source = element.firstFragment.libraryFragment?.source;
11                           ^^^^^^^^^^^^^
12
13Error: The getter 'DiagnosticType' isn't defined for the type 'BuildResolver'.
14        (error) => error.diagnosticCode.type == DiagnosticType.SYNTACTIC_ERROR,

Nothing in my own code had changed. No new packages, no manual edits to pubspec.yaml. So my first instinct — "I broke something" — was wrong. This was a dependency problem, not a code problem.

What's actually happening

The analyzer package (the static analysis engine that build_runner, build, and build_resolvers all lean on internally to read your Dart code) went through a fairly aggressive API cleanup. Symbols like Fragment, firstFragment, DiagnosticType, and the old AnalysisResultWithDiagnostics type were renamed, restructured, or removed outright as part of the analyzer's ongoing migration toward its Element/Fragment model.

The catch: build_runner and build_resolvers are the packages that actually call into analyzer, and they only support specific version ranges of it. If pub resolves your project to a fresh analyzer release before those tooling packages have caught up, you end up with a pubspec.lock that's internally inconsistent — everything "resolves," but the generated code inside build_runner itself no longer compiles against the analyzer version sitting next to it in your pub cache.

This isn't unique to voice_notes. Other Flutter developers hit the same wall after flutter upgrade or a plain pub upgrade, once analyzer crossed into the version where these APIs moved.

Fix 1: pin analyzer down (fastest)

If you just need to unblock yourself right now, pin analyzer to the last version your current build_runner/build_resolvers actually support, via dependency_overrides in pubspec.yaml:

YAML
1dependency_overrides: analyzer: ">=7.4.0 <7.7.0"

Then:

Bash
1flutter pub get dart run build_runner build --delete-conflicting-outputs

This works because it stops pub from resolving to the newer, incompatible analyzer release, without touching anything else in your dependency graph.

Fix 2: upgrade the whole codegen stack together (cleaner long-term)

The more durable fix is to bump build_runner, build, build_resolvers, and analyzer together, since a compatible combination does exist — you just have to move them as a set instead of letting pub pick one newer package on its own:

YAML
1dev_dependencies: build_runner: ^2.8.0  dependency_overrides: analyzer: ">=7.6.0 <8.0.0" build: ">=4.0.0 <5.0.0" build_resolvers: ">=3.0.4 <4.0.0" dart_style: ">=3.1.0 <4.0.0"

Run flutter pub get, then build again. This is the version combination that's actually been tested against each other, rather than whatever the resolver happens to land on.

The habit I picked up from this

I now check flutter pub outdated before doing a blind pub upgrade on any project that leans on build_runner — json_serializable, freezed, injectable, whatever. Codegen tooling has more internal coupling to analyzer than almost anything else in the Flutter ecosystem, so it's the first thing to break when a transitive dependency jumps a major-ish version. A five-second check saves the twenty minutes of staring at a wall of "Fragment isn't a type" errors.

Sources: