ethers.js: "Could not detect network" error on Next.js 14 API endpoint with `JsonRpcProvider`
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 ethers@5.7.2
. 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
About this issue
- Original URL
- State: open
- Created 7 months ago
- Reactions: 9
- Comments: 23 (5 by maintainers)
If you have a direct access to
JsonRpcProvider
construction you can pass an instance of ConnectionInfo. Then you can either useskipFetchSetup
to avoid settingreferrer
to"client"
or provide your own referrer withfetchOptions
.The related code is here: https://github.com/ethers-io/ethers.js/blob/v5.7.2/packages/web/lib.esm/geturl.js#L22
@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
@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 useprovider.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. 😦