Skip to content

always_pass_global_key

v1.0.0 Warning Widget Best Practices

Flags a GlobalKey constructed inside a build method.

build runs on every rebuild, so the key gets a new identity each time. Flutter matches elements by key, concludes the widget is new, and discards the whole subtree it identifies — form contents, scroll position, animation controllers, focus. Nothing throws; the symptom is a form that clears itself when something unrelated rebuilds.

This rule is in the core preset, so it is on with preset: core and every preset above it. No configuration.

See also: Flutter: GlobalKey

class MyForm extends StatelessWidget {
const MyForm({super.key});
@override
Widget build(BuildContext context) {
// New identity every rebuild — the Form's state is thrown away
final formKey = GlobalKey<FormState>();
return Form(key: formKey, child: const SizedBox());
}
}

Hold the key in a State field, so it is created once and survives rebuilds. This also means the widget has to be stateful — a StatelessWidget has nowhere to keep a key that outlives a rebuild.

class MyForm extends StatefulWidget {
const MyForm({super.key});
@override
State<MyForm> createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(key: _formKey, child: const SizedBox());
}
}

ValueKey, ObjectKey and the other LocalKey subclasses are compared by value, not identity, so creating one in build is normal and never reported:

@override
Widget build(BuildContext context) {
return Column(
children: [
for (final item in items) Text(item, key: ValueKey(item)),
],
);
}

Only construction inside a method literally named build is reported. A GlobalKey created in a helper that build calls has the same problem and is not detected:

// Not reported, but just as broken
Widget _field() => Form(key: GlobalKey<FormState>(), child: const SizedBox());
many_lints.yaml
rules:
always_pass_global_key: false

To keep the rule on but skip certain paths, use per-rule exclude.