MetaMask Returns ‘-32603 Internal JSON-RPC error’ with No Revert Reason on Polygon Testnet

I’m building a DApp on the Polygon testnet (the new Amoy network) using MetaMask, ethers.js, and a Solidity smart contract. Whenever I try to call my startMaintenance() function (or several others) from my React frontend, I get an immediate error:

code: -32603
message: "Internal JSON-RPC error."

No revert reason is returned—even though I added try/catch and error decoding with interface.parseError(…). Here’s what I’ve confirmed so far:

  1. Role Checks: I’m calling this as a technician account. In theory, my contract’s onlyTechnician check should pass.
  2. Asset Status: The asset is set to “Broken,” so the require(status == ‘Broken’) check should pass too.
  3. Gas / Funds: I have plenty of test MATIC in the technician’s wallet for gas.
  4. ABI & Address: My ABI is up to date, and the contract address is correct on the Amoy testnet.
  5. No Detailed Revert Data: The node or MetaMask is just returning the generic “Internal JSON-RPC error” with no additional info. I’ve also checked block explorers for a transaction log, but sometimes the TX isn’t even appearing. Has anyone seen this before on Polygon testnets or had the node fail to pass back revert messages? Any ideas on how to coax out the real error reason or confirm where the transaction is failing? This is the function involved in the error:
function startMaintenance(uint _id, string memory startComment) public onlyTechnician {
    require(_id < nextAssetId, "Asset does not exist");
    require(!assets[_id].isDeleted, "Asset is deleted");
    require(keccak256(bytes(assets[_id].status)) == keccak256(bytes("Broken")),
        "Asset must be broken to start maintenance"
    );
    // ...
    assets[_id].status = "Under Maintenance";
    assets[_id].technician = msg.sender;
    emit MaintenanceStarted(_id, msg.sender);
}

and this is the js code

try {
  const tx = await assetManagerContract.startMaintenance(asset.id, startComment);
  await tx.wait();
  alert("Maintenance started!");
} catch (error) {
  console.error("Error handleStartMaintenance:", error);
  // tried to decode revert data, but all I get is the -32603 internal error
}
2 Likes

hi @FilResto , I have asked the developer team to review your question and respond here directly, thank you.

  1. Even if you have sufficient test MATIC, the gas limit for the transaction might be set too low. Try explicitly specifying a higher gas limit in your transaction call:

const tx = await assetManagerContract.startMaintenance(asset.id, startComment, { gasLimit: 300000, });

  1. Network Configuration:
    Ensure your MetaMask is correctly configured for the Amoy testnet. Double-check the RPC URL, Chain ID (80002), and currency symbol (MATIC)

  2. The Amoy testnet may have limitations or bugs with revert message propagation. If possible, try using another RPC endpoint or node provider to see if it resolves the issue.

  3. Update your Solidity contract with more specific error messages:

function startMaintenance() public onlyTechnician { require(status == Status.Broken, "Asset must be in Broken state"); require(msg.sender == technician, "Caller is not the technician"); // More specific checks... status = Status.InMaintenance; // ... }

  1. Debug Transaction Submission

In your frontend code, log the complete transaction object before sending:

const tx = await contract.startMaintenance(); console.log("Transaction sent:", tx); try { const receipt = await tx.wait(); console.log("Transaction confirmed:", receipt); } catch (error) { console.error("Full error object:", error); // Try getting more details if (error.transaction) { console.log("Failed transaction:", error.transaction); } }

1 Like

So it’s more possible that the error is in Amoy side rather than mine? because I checked a lot online and my code, but it seems correct!
If i change the RPC should I redeploy the contract?

Yes, the issue is likely related to the Amoy testnet’s instability or RPC provider rather than your code. Several developers have reported similar problems with Amoy, including generic errors like -32603 and unstable connections.

Changing RPC Provider
You can try switching to another RPC endpoint (e.g., rpc-amoy.polygon.technology or rpc.ankr*com/polygon_amoy), but you do not need to redeploy your contract if the new RPC connects to the same network. The contract remains accessible as long as it is deployed on the Amoy testnet and the RPC points to it.

1 Like

Thank you, one last question, but this error is also in the mainet of Polygon or only for the testnet?

The error can occur on both. But for fun :smiley: change the configuration to polygon mainet and see if the error is displayed.

1 Like

Please check: JSON-RPC methods | MetaMask developer documentation
-32603 it’s an internal JSON-RPC error, often caused by a bad or invalid payload
are you still hitting the same error? Did you check with Polygon about Amoy?

its very weird, because i start with 1 rpc then for few calls it work but then it starts to say error JSON-RPC error, so I change rpc again and it works

1.Public RPCs often have hidden rate limits that throttle requests after a certain threshold, causing intermittent failures.

2.Try private endpoints like Alchemy or Infura for better stability.
Use the Polygon RPC Aggregator (polygon-rpc*com), which has failover and geo-steering mechanisms

3.Or implement Dynamic RPC Switching:
Configure your DApp to automatically switch between multiple RPCs when one fails:

const rpcEndpoints = ["rpc1", "rpc2"];
let currentRpcIndex = 0;

function getRpc() {
  return rpcEndpoints[currentRpcIndex];
}

function switchRpc() {
  currentRpcIndex = (currentRpcIndex + 1) % rpcEndpoints.length;
}

4.Increase Transaction Gas Fees:
Higher fees can prioritize your transactions during congestion.