---
name: flutter-ios-build-cached-class-not-defined
description: |
  Fix Flutter iOS/Android build failures with "The method 'X' isn't defined for the type 'Y'"
  errors that point at a class invocation when the class is in fact defined as a top-level
  class later in the same file. Use when: (1) `flutter analyze` reports zero issues on the
  file, (2) `flutter build ios` / `flutter build apk` / `flutter run` fails claiming a
  newly-added top-level class is undefined, (3) the error line is the call site
  (e.g. `child: _MyNewWidget(...)`) and Dart says it can't resolve it as a method on the
  surrounding state/class, (4) you just added a new top-level class to an existing file
  via an Edit / search-and-replace tool rather than creating a new file, (5) the error
  vanishes if you copy/paste the file's contents into the same file (forcing a full
  re-parse). Root cause: Flutter's incremental Dart-to-kernel compiler under `.dart_tool/`
  has cached the file's translation unit from before your edit. The cache sees the new
  call site but is reading class definitions from the stale snapshot, so resolution
  fails. `flutter analyze` reads files fresh from disk with no cache, which is why it
  disagrees with the build and incorrectly suggests the code is fine.
author: Claude Code
version: 1.0.0
date: 2026-05-14
---

# Flutter iOS Build Says Class Not Defined When Analyze Says It's Fine

## Problem

You add a new top-level class (widget, helper, etc.) to an existing Dart file and
reference it from the `build()` method (or another method) earlier in the same
file. `flutter analyze` reports zero issues. But `flutter build ios` /
`flutter build apk` / `flutter run` fails with:

```
lib/path/to/file.dart:NNN:CC: Error: The method '_MyNewClass' isn't defined for
the type '_SomeStateClass'.
 - '_SomeStateClass' is from 'package:your_app/path/to/file.dart' ('lib/path/to/file.dart').
Try correcting the name to the name of an existing method, or defining a method named '_MyNewClass'.
      bottomNavigationBar: _MyNewClass(
                           ^^^^^^^^^^^
Target kernel_snapshot_program failed: Exception
Failed to package /path/to/project.
Command PhaseScriptExecution failed with a nonzero exit code
```

You re-read the file, the class IS defined at top level later in the same file,
and Dart doesn't care about declaration order. The build is wrong, but it stays
wrong on every retry.

## Trigger Conditions

ALL of these together:

- The "undefined" symbol is a **top-level class** in the **same file** as the
  reference
- You added the class via an Edit / search-and-replace, NOT by creating a new
  `.dart` file
- `flutter analyze <that_file>` reports no issues
- `flutter build <platform>` or `flutter run` fails with the kernel error above
- The compiler clearly DID see your edit (the new reference appears in the
  error message), it just can't find the class definition
- Restarting Xcode / restarting your IDE doesn't help

## Solution

The Dart kernel compiler's incremental cache under `.dart_tool/` is desynced.
Force a clean rebuild.

### Primary fix (recommended — bulletproof)

```bash
flutter clean
flutter pub get
cd ios && pod install && cd ..
flutter run
```

`flutter clean` nukes `build/`, `.dart_tool/`, and `ios/Pods/`. `pod install`
rebuilds the iOS dependency graph from scratch. Total time: 2-5 minutes
depending on pod count.

### Lighter fix (try first if you have many pods and want speed)

```bash
rm -rf build .dart_tool/flutter_build
flutter run
```

This deletes Flutter's build output and the Flutter-specific kernel cache
without touching CocoaPods or `build_runner` outputs. If this doesn't clear
it, fall through to the bulletproof fix.

### What NOT to do

- Don't manually delete `.dart_tool/build/` alone — that's the `build_runner`
  cache (Freezed, json_serializable, etc.). Deleting it forces an unnecessary
  ~30s code-gen regen and isn't the actual culprit.
- Don't only delete `build/ios/` — the staleness lives in the Dart kernel
  cache, not the Xcode build artifacts.
- Don't try to "fix" the file (rename the class, move it, etc.). The file is
  correct.

## Verification

After cleaning, the same `flutter build` / `flutter run` command should
succeed without any code changes. If it still fails with the same error,
either:

1. The clean wasn't thorough — escalate to the bulletproof fix
2. The code actually IS broken (verify by deleting the new class entirely
   and trying again — if it builds, your class is fine; if it doesn't,
   look at the genuinely-broken code instead)

## Why This Happens

`flutter analyze` and `flutter build` use different code paths:

- **`flutter analyze`** invokes the Dart analyzer (`dart analyze`) which
  reads files directly from disk for every invocation. No persistent cache
  between runs. Always sees your edit. Always parses the whole file.
- **`flutter build <platform>`** uses the **incremental Dart kernel
  compiler** to produce a `.dill` snapshot. This compiler caches translation
  units per-file under `.dart_tool/`. When you Edit a file, the cache is
  *supposed* to invalidate via mtime and reparse, but sometimes the
  dependency graph gets desynced — typically when you add new top-level
  declarations that are referenced from already-cached call sites in the
  same file.

The cache state ends up self-inconsistent: it has your new reference but
not your new definition. Dart resolution fails because, from the cache's
perspective, the symbol genuinely doesn't exist.

## Why The Error Message Is Misleading

The error reads as if the class isn't defined ANYWHERE. The "Try correcting
the name" hint suggests typo. Both push you toward staring at the code
looking for a mistake that isn't there. If you don't know about kernel
caching, you can easily burn 30+ minutes thinking you have a scoping bug,
a private-class issue, or a circular import — none of which apply.

## Common Triggers in Practice

This is especially common when:

- An AI assistant uses an Edit tool to append new widget classes to an
  existing file (most common trigger)
- You move a class from one file to another and add it to a file that's
  been recently built
- You add an extension method or extension class with a name similar to
  existing symbols
- You restore a class definition from version control after deleting it

If you create a NEW file containing the class, this bug doesn't appear
because the kernel compiler doesn't have a stale cached translation unit
for a file that didn't exist before.

## Related

If you also use `build_runner` (Freezed, json_serializable, retrofit, etc.)
and need to regenerate code, that's a separate cache:

```bash
dart run build_runner build --delete-conflicting-outputs
```

For stubborn `build_runner` issues, use `dart run build_runner clean` first.
That's the OTHER `.dart_tool/build/` cache (note the directory name overlap —
they are different caches with confusingly similar paths).

## References

- Flutter incremental compiler internals are in
  `package:frontend_server` / `package:vm/kernel_front_end.dart` —
  not officially documented as user-facing behavior.
- `flutter clean` source: `packages/flutter_tools/lib/src/commands/clean.dart`
  in the flutter/flutter repo.
