Mensaje de error
Provided chainId "1" must match the active chainId "137"
También se muestra como
- Cannot sign messages for chainId "1", because MetaMask is switching networks.
Las dApps lo reciben como un error JSON-RPC de `eth_signTypedData_v4` (MetaMask devuelve el código -32603 con este texto). Los números son los ID de cadena de tu dominio y de la billetera. Mientras MetaMask cambia de red, la solicitud falla con «Cannot sign messages for chainId …, because MetaMask is switching networks.».
MetaMask (eth_signTypedData_v3/v4) — validation in @metamask/signature-controller
Qué significa
El `domain.chainId` EIP-712 de los datos tipados no coincide con la red a la que está conectada la billetera en ese momento, y MetaMask se niega a mostrar la solicitud de firma. La regla protege a los usuarios: el ID de cadena forma parte de lo que se firma, y una firma para otra cadena podría reutilizarse en esa cadena. El primer número es el `domain.chainId` de la dApp; el segundo, la cadena activa de la billetera, ambos en decimal.
Por qué ocurre
La dApp tiene chainId fijo en el código
frecuenteUn dominio construido con `chainId: 1` (o con el ID de una red de pruebas) mientras los usuarios se conectan en Polygon, Base, Arbitrum… La solicitud de firma falla para todos los usuarios que no están en esa cadena.
El usuario cambió de red después de que la dApp leyera la cadena
frecuenteLa dApp guardó en caché el ID de cadena en el momento de la conexión y no escuchó `chainChanged`. La siguiente solicitud de firma lleva el valor obsoleto.
chainId como cadena de texto que se interpreta de otra forma
ocasionalMetaMask solo interpreta como hexadecimal un ID de cadena escrito como cadena de texto si lleva el prefijo `0x`. `"89"` es el 89 decimal, no el 0x89 de Polygon (137).
Cómo solucionarlo
- 1.
Construir el dominio a partir de la cadena actual de la billetera
Lee el ID de cadena justo antes de firmar y elige el contrato verificador desplegado en esa cadena.
ts const chainId = await walletClient.getChainId(); // viem // const chainId = Number(await provider.send("eth_chainId", [])); // ethers / raw EIP-1193 const domain = { name: "Example DEX", version: "1", chainId, verifyingContract: dexAddressFor(chainId) }; - 2.
O cambiar la billetera a la cadena requerida
Cuando la orden o el permit solo son válidos en una cadena, solicita primero un cambio de red (`wallet_switchEthereumChain`) y después firma.
ts // If the signature is only valid on one chain (the verifying contract lives there), ask the wallet to switch. await walletClient.switchChain({ id: 1 }); const signature = await walletClient.signTypedData({ account, domain, types, primaryType: "Order", message });