"Mensaje de "Zone mismatch""
Cuando los bindings de Flutter se inicializan en una Zone diferente a la Zone utilizada para `runApp`, se muestra una advertencia en la consola.
Resumen
#A partir de Flutter 3.10, el framework detecta desajustes cuando se usan Zones y los reporta en la consola en compilaciones de depuración (debug).
Contexto
#Las Zones son un mecanismo para gestionar callbacks en Dart.
Aunque son útiles principalmente para anular la lógica de print y Timer en pruebas,
y para capturar errores en pruebas,
a veces se utilizan para limitar el alcance (scoping) de variables globales
a ciertas partes de una aplicación.
Flutter requiere (y siempre ha requerido)
que todo el código del framework se ejecute en la misma zone.
Notablemente, esto significa que las llamadas a
WidgetsFlutterBinding.ensureInitialized() deben ejecutarse en la misma zone
que las llamadas a runApp().
Históricamente, Flutter no detectaba estos desajustes.
Esto a veces conduce a problemas oscuros y difíciles de depurar.
Por ejemplo,
un callback para la entrada del teclado podría invocarse
usando una zone que no tiene acceso a los zoneValues que espera.
En nuestra experiencia,
la mayoría, si no todo el código que utiliza Zones
de una manera que no garantiza que todas las partes del
framework de Flutter estén funcionando en la misma Zone,
tiene algún error (bug) latente.
A menudo, estos errores parecen no estar relacionados con el uso de Zones.
Para ayudar a los desarrolladores que accidentalmente hayan violado esta invariante, a partir de Flutter 3.10, se muestra una advertencia no fatal en las compilaciones de depuración cuando se detecta un desajuste. La advertencia se ve de la siguiente manera:
════════ Exception caught by Flutter framework ════════════════════════════════════
The following assertion was thrown during runApp:
Zone mismatch.
The Flutter bindings were initialized in a different zone than is now being used.
This will likely cause confusion and bugs as any zone-specific configuration will
inconsistently use the configuration of the original binding initialization zone or
this zone based on hard-to-predict factors such as which zone was active when a
particular callback was set.
It is important to use the same zone when calling `ensureInitialized` on the
binding as when calling `runApp` later.
To make this warning fatal, set BindingBase.debugZoneErrorsAreFatal to true before
the bindings are initialized (i.e. as the first statement in `void main() { }`).
[...]
═══════════════════════════════════════════════════════════════════════════════════
La advertencia se puede hacer fatal
estableciendo BindingBase.debugZoneErrorsAreFatal
en true.
Esta bandera podría cambiarse para que sea true de forma predeterminada en una versión futura de Flutter.
Guía de migración
#La mejor manera de silenciar este mensaje es eliminar el uso de Zones dentro de la aplicación. Las Zones pueden ser muy difíciles de depurar, porque son esencialmente variables globales, y rompen la encapsulación. La mejor práctica es evitar variables globales y zones.
Si eliminar las zones no es una opción
(for example porque la aplicación depende de una biblioteca de terceros
que depende de las zones para su configuración),
entonces las diversas llamadas al framework de Flutter
deberían moverse para estar todas en la misma zone.
Típicamente, esto significa mover la llamada a
WidgetsFlutterBinding.ensureInitialized() al
mismo closure que la llamada a runApp().
Esto puede resultar incómodo cuando la zone en la que se ejecuta runApp
se está inicializando con zoneValues obtenidos de un complemento (plugin)
(lo que requiere que se haya llamado a WidgetsFlutterBinding.ensureInitialized()).
Una opción en este tipo de escenario es
colocar un objeto mutable en zoneValues, y
actualizar ese objeto con el valor una vez que esté disponible.
import 'dart:async';
import 'package:flutter/material.dart';
class Mutable<T> {
Mutable(this.value);
T value;
}
void main() {
var myValue = Mutable<double>(0.0);
Zone.current.fork(
zoneValues: {
'myKey': myValue,
}
).run(() {
WidgetsFlutterBinding.ensureInitialized();
var newValue = ...; // obtain value from plugin
myValue.value = newValue; // update value in Zone
runApp(...);
});
}
En el código que necesita usar myKey,
se puede obtener de forma indirecta usando Zone.current['myKey'].value.
Cuando tal solución no funcione
porque una dependencia de terceros requiere el uso
de un tipo específico para una clave de zoneValues específica,
todas las llamadas a la dependencia pueden
envolverse en llamadas de Zone que proporcionen valores adecuados.
Se recomienda encarecidamente que los paquetes que usan zones de esta manera migren a soluciones más mantenibles.
Timeline
#Introducido en la versión: 3.9.0-9.0.pre
En la versión estable: 3.10.0
Referencias
#Documentación de la API:
Issues relevantes:
- Issue 94123: El framework de Flutter no advierte cuando se llama a ensureInitialized en una zone diferente a la de runApp
PRs relevantes:
- PR 122836: Afirma (Assert) que se llama a runApp en la misma zone que binding.ensureInitialized
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.