ethers.js icon indicating copy to clipboard operation
ethers.js copied to clipboard

"Could not detect network" error on Next.js 14 API endpoint with `JsonRpcProvider`

Open DavNej opened this issue 2 years ago • 25 comments
trafficstars

Ethers Version

5.7.2

Search Terms

NETWORK_ERROR, next 14, JsonRpcProvider, next api endpoint

Describe the Problem

Issue:

I am encountering what I think is a compatibility issue between Next.js 14 and [email protected] . When attempting to instantiate a JsonRpcProvider on an API endpoint, I consistently receive a could not detect network error.

Steps to Reproduce:

- Upgrade Next.js to version 14.
- Use ethers.js version 5.7.2.
- Instantiate on a Next API endpoint a `JsonRpcProvider` with a valid RPC URL .

Expected Behavior:

The JsonRpcProvider should be successfully instantiated without any "could not detect network" errors.

Actual Behavior:

Encountering a "could not detect network" error when attempting to instantiate a JSONRPCProvider.

Additional Information:

The issue is not present when using Next.js 13.
Downgrading to Next.js 13 resolves the problem, but a solution for Next.js 14 compatibility is desired.

Environment:

Next.js version: 14
ethers.js version: 5.7.2
Provider: JSONRPCProvider with a valid RPC URL

Note:

Any guidance or workaround to make ethers.js version 5.7.2, specifically with JSONRPCProvider, compatible with Next.js 14 would be highly appreciated.

Code Snippet

import { NextResponse } from 'next/server'
import { ethers, type BigNumber } from 'ethers'
import abi from 'abi.json'

const contractInterface = new ethers.utils.Interface(abi)

export async function GET(request: Request) {
  const provider = new ethers.providers.JsonRpcProvider(<RPC_TARGET>)

  const wallet = new ethers.Wallet(<PRIVATE_KEY>, provider)
  const contract = new ethers.Contract(
    <CONTRACT_ADDRESS>,
    contractInterface,
    wallet
  )

  try {
    const handlePrice: BigNumber = await contract.getHandlePrice(handle)
    return NextResponse.json<{ handlePrice: BigNumber }>({ handlePrice })
  } catch (err) {
    console.error('💥', err)
    return NextResponse.json(err, { status: 500 })
  }
}

Contract ABI

[
  {
    "inputs": [],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "HandleContainsInvalidCharacters",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "HandleFirstCharInvalid",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "HandleLengthInvalid",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "previousAdmin",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newAdmin",
        "type": "address"
      }
    ],
    "name": "AdminChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "approved",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "ApprovalForAll",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "beacon",
        "type": "address"
      }
    ],
    "name": "BeaconUpgraded",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "profileId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "newCid",
        "type": "string"
      }
    ],
    "name": "CidUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "profileId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "delegate",
        "type": "address"
      }
    ],
    "name": "DelegateAdded",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "profileId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "delegate",
        "type": "address"
      }
    ],
    "name": "DelegateRemoved",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint8",
        "name": "version",
        "type": "uint8"
      }
    ],
    "name": "Initialized",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "user",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "profileId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "handle",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "platformId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "fee",
        "type": "uint256"
      }
    ],
    "name": "Mint",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "mintFee",
        "type": "uint256"
      }
    ],
    "name": "MintFeeUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "enum TalentLayerID.MintStatus",
        "name": "mintStatus",
        "type": "uint8"
      }
    ],
    "name": "MintStatusUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "price",
        "type": "uint256"
      }
    ],
    "name": "ShortHandlesMaxPriceUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "forwarder",
        "type": "address"
      }
    ],
    "name": "TrustedForwarderAdded",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "forwarder",
        "type": "address"
      }
    ],
    "name": "TrustedForwarderRemoved",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "implementation",
        "type": "address"
      }
    ],
    "name": "Upgraded",
    "type": "event"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "_delegate",
        "type": "address"
      }
    ],
    "name": "addDelegate",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_forwarder",
        "type": "address"
      }
    ],
    "name": "addTrustedForwarder",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_platformId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "_userAddress",
        "type": "address"
      },
      {
        "internalType": "string",
        "name": "_handle",
        "type": "string"
      }
    ],
    "name": "freeMint",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "getApproved",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "_handle",
        "type": "string"
      }
    ],
    "name": "getHandlePrice",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_address",
        "type": "address"
      }
    ],
    "name": "getOriginatorPlatformIdByAddress",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "hasActivity",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "ids",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_talentLayerPlatformIdAddress",
        "type": "address"
      }
    ],
    "name": "initialize",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      }
    ],
    "name": "isApprovedForAll",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "_address",
        "type": "address"
      }
    ],
    "name": "isDelegate",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "_address",
        "type": "address"
      }
    ],
    "name": "isOwnerOrDelegate",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "isServiceContract",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "forwarder",
        "type": "address"
      }
    ],
    "name": "isTrustedForwarder",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      }
    ],
    "name": "isValid",
    "outputs": [],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_address",
        "type": "address"
      },
      {
        "internalType": "string",
        "name": "_handle",
        "type": "string"
      },
      {
        "internalType": "bytes32[]",
        "name": "_proof",
        "type": "bytes32[]"
      }
    ],
    "name": "isWhitelisted",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_platformId",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "_handle",
        "type": "string"
      }
    ],
    "name": "mint",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "mintFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_address",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "_platformId",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "_handle",
        "type": "string"
      }
    ],
    "name": "mintForAddress",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "mintStatus",
    "outputs": [
      {
        "internalType": "enum TalentLayerID.MintStatus",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ownerOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_tokenId1",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_tokenId2",
        "type": "uint256"
      }
    ],
    "name": "ownersOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "profiles",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "id",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "handle",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "platformId",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "dataUri",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "proxiableUUID",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "_delegate",
        "type": "address"
      }
    ],
    "name": "removeDelegate",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_forwarder",
        "type": "address"
      }
    ],
    "name": "removeTrustedForwarder",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "bytes",
        "name": "data",
        "type": "bytes"
      }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "setApprovalForAll",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      }
    ],
    "name": "setHasActivity",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_address",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "_isServiceContract",
        "type": "bool"
      }
    ],
    "name": "setIsServiceContract",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "root",
        "type": "bytes32"
      }
    ],
    "name": "setWhitelistMerkleRoot",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes4",
        "name": "interfaceId",
        "type": "bytes4"
      }
    ],
    "name": "supportsInterface",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "name": "takenHandles",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "talentLayerPlatformIdContract",
    "outputs": [
      {
        "internalType": "contract ITalentLayerPlatformID",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "tokenURI",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_mintFee",
        "type": "uint256"
      }
    ],
    "name": "updateMintFee",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "enum TalentLayerID.MintStatus",
        "name": "_mintStatus",
        "type": "uint8"
      }
    ],
    "name": "updateMintStatus",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_profileId",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "_newCid",
        "type": "string"
      }
    ],
    "name": "updateProfileData",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_shortHandlesMaxPrice",
        "type": "uint256"
      }
    ],
    "name": "updateShortHandlesMaxPrice",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newImplementation",
        "type": "address"
      }
    ],
    "name": "upgradeTo",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newImplementation",
        "type": "address"
      },
      {
        "internalType": "bytes",
        "name": "data",
        "type": "bytes"
      }
    ],
    "name": "upgradeToAndCall",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_platformId",
        "type": "uint256"
      },
      {
        "internalType": "string",
        "name": "_handle",
        "type": "string"
      },
      {
        "internalType": "bytes32[]",
        "name": "_proof",
        "type": "bytes32[]"
      }
    ],
    "name": "whitelistMint",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "withdraw",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

Errors

could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.7.2)
    at Logger.makeError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:240:23)
    at Logger.throwError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:249:20)
    at JsonRpcProvider.eval (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:513:27)
    at Generator.throw (<anonymous>)
    at rejected (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:34:40)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at listOnTimeout (node:internal/timers:538:9)
    at process.processTimers (node:internal/timers:512:7) {
  reason: 'could not detect network',
  code: 'NETWORK_ERROR',
  event: 'noNetwork'
}

Environment

Other (please specify)

Environment (Other)

NextJS 14

DavNej avatar Nov 17 '23 09:11 DavNej

Just got the same issue on my side. Viem worked, but of course .. that isn't very assuring. Instead, I added v6 to my project using npm package aliasing which works. ni ethers-latest@npm:ethers@v6

HansBhatia avatar Dec 20 '23 17:12 HansBhatia

👋 Hello, I'm also encountering the same issue when upgrading from Next.js 13 to 14 with Ethers 5.7.2.

I want to add my voice to highlight its impact. If there are any updates or workarounds, I'd greatly appreciate it. Thanks!

remibeaufils avatar Jan 05 '24 16:01 remibeaufils

Just got bitten by this in production via a silent failure by a dependency (itself using Ethers). Manifested as a promise that never resolved and resulted in a lot of user confusion until we arrived at the root cause!

dsimmons avatar Jan 05 '24 19:01 dsimmons

@dsimmons Are you using v5 or v6? In v6, you can detect this error using provider.on("error", …), which you can either wait for the link to come back up or use provider.destroy() and use whatever recovery method you use, depending on why the network isn’t detectable (i.e. the node is failing to reply to eth_chainId.

If connecting to a static network, specifying that network will also skip this problem. You will likely still get an error, but it will be something you can trap using try…catch on the calls.

This isn’t generally trappable because it happens in the constructor, and we don’t have async constructors. :(

ricmoo avatar Jan 05 '24 22:01 ricmoo

@ricmoo Actually, neither! :sweat_smile:

I am however using Irys via their JS SDK, which itself uses v5, so I don't have a lot of control over this issue unfortunately (transitive dependency).

dsimmons avatar Jan 06 '24 00:01 dsimmons

I do encounter the same issue... I think no provider are working anymore with next 14 and to complete this thread, I will add that AlchemyProvider is also failing which i think is linked. The error is totally different ('Referrer "client" is not a valid URL') but I put the stacktrace here if it can help to find and solve the problem:

Error: missing revert data in call exception; Transaction reverted without a reason string [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (data="0x", transaction={"to":"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzz","data":"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzzz","accessList":null}, error={"reason":"missing response","code":"SERVER_ERROR","requestBody":"{\"method\":\"eth_call\",\"params\":[{\"to\":\"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzz\",\"data\":\"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\"},\"latest\"],\"id\":42,\"jsonrpc\":\"2.0\"}","requestMethod":"POST","serverError":{},"url":"https://polygon-mumbai.g.alchemy.com/v2/abcabcabcabcabcabc"}, code=CALL_EXCEPTION, version=providers/5.7.0) at Logger.makeError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:240:23) at Logger.throwError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:249:20) at checkError (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:103:16) at AlchemyProvider.eval (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:729:24) at Generator.throw (<anonymous>) at rejected (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:34:40) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { reason: 'missing revert data in call exception; Transaction reverted without a reason string', code: 'CALL_EXCEPTION', data: '0x', transaction: { to: '0xzzzzzzzzzzzzzzzzzzzzzzzzzzzz', data: '0xzzzzzzzzzzzzzzzzzzzzzzzzzzzzz', accessList: null }, error: Error: missing response (requestBody="{\"method\":\"eth_call\",\"params\":[{\"to\":\"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzz\",\"data\":\"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\"},\"latest\"],\"id\":42,\"jsonrpc\":\"2.0\"}", requestMethod="POST", serverError={}, url="https://polygon-mumbai.g.alchemy.com/v2/abcabcabcabcabcabc", code=SERVER_ERROR, version=web/5.7.0) at Logger.makeError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:240:23) at Logger.throwError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:249:20) at eval (webpack-internal:///(rsc)/./node_modules/@ethersproject/web/lib.esm/index.js:259:32) at Generator.throw (<anonymous>) at rejected (webpack-internal:///(rsc)/./node_modules/@ethersproject/web/lib.esm/index.js:31:40) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { reason: 'missing response', code: 'SERVER_ERROR', requestBody: '{"method":"eth_call","params":[{"to":"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzz","data":"0xzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"},"latest"],"id":42,"jsonrpc":"2.0"}', requestMethod: 'POST', serverError: TypeError: Referrer "client" is not a valid URL. at new Request (node:internal/deps/undici/undici:5361:21) at R (C:\Users\emeri\Documents\GITHUB\JARVIX\jvx-template\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:35:342062) ... 42 lines matching cause stack trace ... at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { [cause]: [TypeError] }, url: 'https://polygon-mumbai.g.alchemy.com/v2/abcabcabcabcabcabc' } }

tazous avatar Jan 10 '24 17:01 tazous

here's a simple example of a server method:

export async function GET() {
  const provider = new ethers.providers.JsonRpcProvider(`https://polygon-mumbai.infura.io/v3/${process.env.INFURA_API_KEY}`);
  const price = await provider.getGasPrice();
  return NextResponse.json({ message: 'we are live.' });
}

throws an error

Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.7.2)
    at Logger.makeError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:240:23)
    at Logger.throwError (webpack-internal:///(rsc)/./node_modules/@ethersproject/logger/lib.esm/index.js:249:20)
    at JsonRpcProvider.eval (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:513:27)
    at Generator.throw (<anonymous>)
    at rejected (webpack-internal:///(rsc)/./node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js:34:40)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at listOnTimeout (node:internal/timers:538:9)
    at process.processTimers (node:internal/timers:512:7) {
  reason: 'could not detect network',
  code: 'NETWORK_ERROR',
  event: 'noNetwork'

using ethers 5.7.2

freeslugs avatar Jan 15 '24 03:01 freeslugs

@tazous Yoir error seems unrelated. The contract you are calling returned 0x which means the service is working fine, but the call returned bad data. This most often happens when the the contract address is incorrect, the contract isn’t deployed yet (such as calling a method before waiting for the contract in a test case before waiting for the deployment tx to be mined) or the correct address is used, but on the wrong chain.

There can be other reasons you get this, but those are the most common.

ricmoo avatar Jan 15 '24 05:01 ricmoo

@freeslugs can you verify using console.log(process.env.INFURA_API_KEY) that your environment variable is correct?

I see this type of problem often, which is that the dotenv (or such) is not being configured in the environment correctly, which results in the URL becoming malformed.

ricmoo avatar Jan 15 '24 05:01 ricmoo

@ricmoo On my side, the contract call is working fine when using nextjs 13 and once switching to nextjs 14, I get this error with the exact same call, that's why I suspect it to be a related error... (I get the 'no network' error when using jsonrcp as the others, and the 'Referrer "client" is not a valid URL' error when using alchemy provider and everything is back to normal if I switch back to nextjs13)

And to go further in that direction, after upgrading to ethers v6+ (with all the migration implied), my same code is finally working fine on nextjs 14... I think all this points to a compatibility issue between ethers 5.7 and nextjs 14

tazous avatar Jan 15 '24 14:01 tazous

@freeslugs can you verify using console.log(process.env.INFURA_API_KEY) that your environment variable is correct?

I see this type of problem often, which is that the dotenv (or such) is not being configured in the environment correctly, which results in the URL becoming malformed.

Yah it works. My solution was to switch to viem. API is relatively similar :)

const provider = createPublicClient({
      chain: polygonMumbai,
      transport: http(`https://polygon-mumbai.infura.io/v3/${process.env.INFURA_API_KEY}`),
    });

freeslugs avatar Jan 15 '24 16:01 freeslugs

@tazous Thanks for the info! Glad to hear NextJS 14 works fine with v6.

If you figure out any extra info on why v5 is affected, let me know as I am planning a small number of changes to port back to v5. :)

ricmoo avatar Jan 15 '24 16:01 ricmoo

I'm affected by this as well. next@14 leads to the no network error w/ ethers5 when called serverside in app/api/**/*.ts const provider = new ethers.providers.JsonRpcBatchProvider(RPC_URL); console.log(await provider.getNetwork()); . [email protected] downgrade allows it to work with ethers5

mrbasado avatar Jan 15 '24 16:01 mrbasado

@mrbasado Can you provide any additional details? Can someone provide me a minimal NextJS 14 and ethers v5 reproduction steps? Like possibly a single page app?

ricmoo avatar Jan 15 '24 16:01 ricmoo

@mrbasado Can you provide any additional details? Can someone provide me a minimal NextJS 14 and ethers v5 reproduction steps? Like possibly a single page app?

Try mine :) https://github.com/ethers-io/ethers.js/issues/4469#issuecomment-1891231934

freeslugs avatar Jan 16 '24 03:01 freeslugs

@ricmoo Thank you for looking. here is a quick demo: https://github.com/mrbasado/next14-ethers5 @freeslugs let me know if this covers your use-case as well.

mrbasado avatar Jan 23 '24 00:01 mrbasado

@ricmoo We are still impacted by this issue. let me know if you need any clarification on the example - hopefully the readme covers it!

mrbasado avatar Jan 29 '24 16:01 mrbasado

If you have a direct access to JsonRpcProvider construction you can pass an instance of ConnectionInfo. Then you can either use skipFetchSetup to avoid setting referrer to "client" or provide your own referrer with fetchOptions.

new JsonRpcProvider({
      fetchOptions: {
        referrer: "https://myapp.xyz",
      },
      url: 'rpcurl'
    })

new JsonRpcProvider({
      skipFetchSetup: true,
      url: 'rpcurl'
    })

The related code is here: https://github.com/ethers-io/ethers.js/blob/v5.7.2/packages/web/lib.esm/geturl.js#L22

MichaelBorde avatar Feb 07 '24 14:02 MichaelBorde

Happened to me as well setting the referrer seems to be the solution. Thanks to @MichaelBorde

Man-Jain avatar Feb 09 '24 22:02 Man-Jain

This error only occurs using nextjs14 but not nextjs13 page route, despite ethers.js version.

ChiuMungZitAlexander avatar Feb 20 '24 06:02 ChiuMungZitAlexander

Ether v6 has more issues like [TypeError: Cannot read properties of undefined (reading 'JsonRpcProvider')](https://ethereum.stackexchange.com/questions/144451/typeerror-cannot-read-properties-of-undefined-reading-jsonrpcprovider)

How do you manage that with nextjs 14?

I tried to run it with nextjs13 with AppDir, still the same error. It only works in server side.

vincent38wargnier avatar Feb 20 '24 22:02 vincent38wargnier

I use next@14 and ehters v5. This solution works for me.

If you have a direct access to JsonRpcProvider construction you can pass an instance of ConnectionInfo. Then you can either use skipFetchSetup to avoid setting referrer to "client" or provide your own referrer with fetchOptions.

new JsonRpcProvider({
      fetchOptions: {
        referrer: "https://myapp.xyz",
      },
      url: 'rpcurl'
    })

new JsonRpcProvider({
      skipFetchSetup: true,
      url: 'rpcurl'
    })

The related code is here: https://github.com/ethers-io/ethers.js/blob/v5.7.2/packages/web/lib.esm/geturl.js#L22

o-tsaruk avatar Mar 10 '24 09:03 o-tsaruk

I was experiencing the same issue, and it was resolved by updating to NextJs version 13 while keeping the ethers package at version 5.7.2.

codeesura avatar Mar 22 '24 21:03 codeesura

I use next@14 and ehters v5. This solution works for me.

If you have a direct access to JsonRpcProvider construction you can pass an instance of ConnectionInfo. Then you can either use skipFetchSetup to avoid setting referrer to "client" or provide your own referrer with fetchOptions.

new JsonRpcProvider({
      fetchOptions: {
        referrer: "https://myapp.xyz",
      },
      url: 'rpcurl'
    })

new JsonRpcProvider({
      skipFetchSetup: true,
      url: 'rpcurl'
    })

The related code is here: https://github.com/ethers-io/ethers.js/blob/v5.7.2/packages/web/lib.esm/geturl.js#L22

This works 💯

markibanez avatar Jun 14 '24 07:06 markibanez