Error message
invalid signature length
Also printed as
- Error: invalid signature length
viem (TypeScript) — recoverMessageAddress / recoverAddress / recoverTypedDataAddress / recoverPublicKey
What it means
viem's recovery functions accept a hex or byte signature of exactly 65 bytes (r‖s‖v) and stop with this plain `Error` for any other length — including the 64-byte EIP-2098 compact form, which viem supports only through explicit conversion helpers. Nothing was recovered; the signature is in a different format, or it is not an EOA signature at all.
Why it happens
A 64-byte compact (EIP-2098) signature
commonSome wallets, relayers and contracts store signatures in the compact form (yParity folded into s). ethers accepts it directly; viem's `recover*` functions do not.
A smart-account signature
commonERC-1271 and ERC-6492 signatures from Safe, Coinbase Smart Wallet or other smart accounts are longer than 65 bytes and cannot be recovered to an address; they must be checked against the account contract.
Base64 or double-hex encoding
occasionalA signature transported as base64, or a hex string encoded again as hex, has the wrong length once viem reads it.
How to fix it
- 1.
Convert compact signatures before recovering
`parseCompactSignature` plus `compactSignatureToSignature` turns the 64-byte form into the 65-byte one.
ts import { compactSignatureToSignature, parseCompactSignature, recoverMessageAddress, serializeSignature, size } from "viem"; const sig = size(signature) === 64 ? serializeSignature(compactSignatureToSignature(parseCompactSignature(signature))) : signature; const signer = await recoverMessageAddress({ message, signature: sig }); - 2.
Use publicClient.verifyMessage for wallets in general
A public client verifies EOA signatures locally and smart-account signatures through ERC-1271/ERC-6492, so the same code works for every wallet type.
ts import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; // Handles EOAs, ERC-1271 smart accounts and ERC-6492 (undeployed) accounts. const client = createPublicClient({ chain: mainnet, transport: http(process.env.RPC_URL) }); const valid = await client.verifyMessage({ address, message, signature });