Mensagem de erro
Provided chainId "1" must match the active chainId "137"
Também aparece como
- Cannot sign messages for chainId "1", because MetaMask is switching networks.
Os dApps recebem isso como um erro JSON-RPC de `eth_signTypedData_v4` (o MetaMask retorna o código -32603 com este texto). Os números são os IDs da cadeia do seu domínio e da carteira. Enquanto o MetaMask está trocando de rede, a requisição falha com “Cannot sign messages for chainId …, because MetaMask is switching networks.”.
MetaMask (eth_signTypedData_v3/v4) — validation in @metamask/signature-controller
O que significa
O `domain.chainId` EIP-712 dos dados tipados é diferente da rede à qual a carteira está conectada no momento, e o MetaMask se recusa a mostrar a solicitação de assinatura. A regra protege os usuários: o ID da cadeia faz parte do que é assinado, e uma assinatura feita para outra cadeia poderia ser repetida (replay) nela. O primeiro número é o `domain.chainId` do dApp; o segundo, a cadeia ativa da carteira, ambos em decimal.
Por que acontece
O dApp fixa o chainId no código
comumUm domínio montado com `chainId: 1` (ou com o ID de uma rede de teste) enquanto os usuários se conectam pela Polygon, pela Base, pela Arbitrum… A solicitação de assinatura falha para todo usuário que não está nessa cadeia.
O usuário trocou de rede depois que o dApp leu a cadeia
comumO dApp guardou em cache o ID da cadeia no momento da conexão e não escutou o `chainChanged`. A próxima solicitação de assinatura leva o valor desatualizado.
O chainId como string interpretada de outra forma
ocasionalO MetaMask só interpreta IDs da cadeia em forma de string como hexadecimais quando têm o prefixo `0x`. `"89"` é 89 em decimal, e não o 0x89 (137) da Polygon.
Como corrigir
- 1.
Montar o domínio a partir da cadeia atual da carteira
Leia o ID da cadeia logo antes de assinar e escolha o contrato verificador implantado nessa cadeia.
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.
Ou trocar a carteira para a cadeia exigida
Quando a ordem ou o permit só vale em uma cadeia, peça primeiro a troca de rede (`wallet_switchEthereumChain`) e depois assine.
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 });