Skip to main content

Overview

When integrating with CoW Protocol, errors can occur at four distinct stages of the order lifecycle:
  1. Quoting — requesting a price quote from the API
  2. Signing — constructing and signing the order client-side
  3. Submission — posting the signed order to the orderbook
  4. Settlement — solver execution after the order is accepted
This reference documents every common error at each stage, along with its root cause and a concrete fix.
All API errors return a JSON body with an errorType and description field. Always parse the response body for details rather than relying solely on the HTTP status code.

Quoting Errors

These errors are returned by POST /api/v1/quote when requesting a price quote.
FieldValue
HTTP Status400 Bad Request
Error CodeSellAmountDoesNotCoverFee
Root CauseThe sell amount is too small to cover the network costs (gas) required to settle the trade. This is common when trading very small amounts of high-value tokens or when gas prices are elevated.
Fix:
  • Increase the sellAmountBeforeFee to a value that exceeds the estimated fee.
  • Try a different token pair with lower gas overhead.
  • Wait for lower gas conditions if trading on Ethereum mainnet.
FieldValue
HTTP Status400 Bad Request
Error CodeNoLiquidity
Root CauseNo liquidity path was found between the sell and buy tokens at the requested amount. This can happen when a token is new, has very thin liquidity, or the amount is too large for available pools.
Fix:
  • Verify both token addresses are correct and checksummed.
  • Confirm the tokens have on-chain liquidity (check on a DEX aggregator).
  • Try a smaller trade amount.
  • Try routing through a more liquid intermediate token (e.g., WETH or USDC) by splitting into two trades.
FieldValue
HTTP Status400 Bad Request
Error CodeUnsupportedToken
Root CauseOne or both tokens are not supported by CoW Protocol. Tokens may be unsupported due to fee-on-transfer mechanics, rebasing behavior, or simply not being indexed.
Fix:
  • Verify the token contract address is correct for the target chain.
  • Check whether the token is a fee-on-transfer or rebasing token, as these are generally not supported.
  • Consult the supported token list for the relevant network.
FieldValue
HTTP Status400 Bad Request
Error CodeInvalidParameter
Root CauseOne or more request parameters are missing, malformed, or invalid. Common variants include missing required fields (sellToken, buyToken, from), invalid Ethereum addresses, non-numeric amounts, or an unsupported kind value.
Fix:
  • Ensure all required fields are present: sellToken, buyToken, from, kind, and either sellAmountBeforeFee (for sell orders) or buyAmountAfterFee (for buy orders).
  • Validate that all addresses are valid, checksummed, 42-character hex strings.
  • Ensure amounts are passed as decimal strings (not hex), without decimals.
  • Use "sell" or "buy" for the kind field.
FieldValue
HTTP Status429 Too Many Requests
Error CodeRateLimited
Root CauseYou have exceeded the API rate limit. Quote requests are limited to approximately 10 requests per second.
Fix:
  • Implement exponential backoff with jitter between retries.
  • Respect Retry-After headers when present.
  • Cache quote responses where appropriate to reduce request volume.
  • See the Common Patterns section for a recommended retry strategy.
FieldValue
HTTP Status500 Internal Server Error
Error CodeInternalServerError
Root CauseA transient error occurred on the API server. This is typically temporary and not caused by your request.
Fix:
  • Retry the request with exponential backoff (start at 1 second, max 30 seconds).
  • If the error persists for more than a few minutes, check CoW Protocol status for outages.
  • Try the staging environment (barn.api.cow.fi) to determine if the issue is environment-specific.

Signing Errors

Signing errors occur client-side when constructing the EIP-712 typed data signature. These are not API responses but runtime errors in your signing code.
Signing errors are the most common integration issue. The EIP-712 domain and type definitions must match exactly what the settlement contract expects, or the order will be rejected on submission.
FieldValue
Error TypeClient-side / signature verification failure
Root CauseThe EIP-712 domain separator used for signing does not match the target chain. This happens when chainId is wrong (e.g., using 1 for Gnosis Chain) or verifyingContract does not point to the correct GPv2Settlement contract.
Fix:Use the correct domain parameters per chain:
ChainchainIdSettlement Contract
Ethereum10x9008D19f58AAbD9eD0D60971565AA8510560ab41
Gnosis Chain1000x9008D19f58AAbD9eD0D60971565AA8510560ab41
Arbitrum One421610x9008D19f58AAbD9eD0D60971565AA8510560ab41
Base84530x9008D19f58AAbD9eD0D60971565AA8510560ab41
Sepolia111551110x9008D19f58AAbD9eD0D60971565AA8510560ab41
The domain must be:
const domain = {
  name: 'Gnosis Protocol',
  version: 'v2',
  chainId: <TARGET_CHAIN_ID>,
  verifyingContract: '0x9008D19f58AAbD9eD0D60971565AA8510560ab41'
}
The settlement contract address is the same across all supported chains, but the chainId must match the network you are submitting to.
FieldValue
Error TypeClient-side / EIP-712 encoding error
Root CauseThe order struct fields or their types do not match the EIP-712 type definition expected by the settlement contract. Common mistakes include missing fields, wrong field order, or incorrect types (e.g., using uint128 instead of uint256).
Fix:Use the exact type definition:
const types = {
  Order: [
    { name: 'sellToken', type: 'address' },
    { name: 'buyToken', type: 'address' },
    { name: 'receiver', type: 'address' },
    { name: 'sellAmount', type: 'uint256' },
    { name: 'buyAmount', type: 'uint256' },
    { name: 'validTo', type: 'uint32' },
    { name: 'appData', type: 'bytes32' },
    { name: 'feeAmount', type: 'uint256' },
    { name: 'kind', type: 'string' },
    { name: 'partiallyFillable', type: 'bool' },
    { name: 'sellTokenBalance', type: 'string' },
    { name: 'buyTokenBalance', type: 'string' },
  ]
}
Alternatively, use the SDK’s signOrder helper which handles this automatically. See the signing schemes reference for full details.
FieldValue
Error TypeClient-side / signer mismatch
Root CauseThe wallet or private key used to sign the order does not correspond to the from address specified in the quote request. The API will reject the signature because recovered signer differs from the expected order owner.
Fix:
  • Ensure the signer (private key or connected wallet) matches the from address used when requesting the quote.
  • When using a smart contract wallet (e.g., Safe), use the presign signing scheme instead of eip712.
  • Double-check that you are not mixing up accounts in a multi-wallet setup.

Submission Errors

These errors are returned by POST /api/v1/orders when submitting a signed order to the orderbook.
FieldValue
HTTP Status400 Bad Request
Error CodeInvalidSignature
Root CauseThe signature attached to the order could not be verified. This is typically caused by a domain separator mismatch, incorrect signing scheme declaration, or the signature being generated by the wrong account.
Fix:
  • Verify the signingScheme field matches how you actually signed (e.g., eip712, ethsign, presign).
  • Check the EIP-712 domain separator matches the target chain (see Signing Errors).
  • Ensure the signer address matches the order’s from/owner field.
  • If using ethsign, remember the message is prefixed with \x19Ethereum Signed Message:\n32 before hashing.
FieldValue
HTTP Status400 Bad Request
Error CodeDuplicateOrder
Root CauseAn order with the same UID already exists in the orderbook. Order UIDs are deterministic based on order parameters and the owner address.
Fix:
  • Use the existing order’s UID to track its status via GET /api/v1/orders/{uid}.
  • If you need a new order, change at least one parameter (e.g., validTo, sellAmount, or appData) to produce a different UID.
FieldValue
HTTP Status400 Bad Request
Error CodeInsufficientBalance
Root CauseThe order owner’s wallet does not hold enough of the sell token to cover the sell amount plus fees.
Fix:
  • Check the owner’s on-chain balance of the sell token.
  • Ensure the balance covers sellAmount + feeAmount.
  • If the balance will be available by settlement time (e.g., from a pending transaction), note that the API validates balance at submission time.
FieldValue
HTTP Status400 Bad Request
Error CodeInsufficientAllowance
Root CauseThe GPv2VaultRelayer contract has not been approved to spend the sell token on behalf of the order owner. CoW Protocol requires token approval for the VaultRelayer, not the Settlement contract.
Fix:
  • Approve the GPv2VaultRelayer contract (0xC92E8bdf79f0507f65a392b0ab4667716BFE0110) to spend the sell token.
  • The approval amount must be at least sellAmount + feeAmount.
  • For convenience, many integrations approve type(uint256).max.
// Example approval using viem
await walletClient.writeContract({
  address: sellTokenAddress,
  abi: erc20Abi,
  functionName: 'approve',
  args: [
    '0xC92E8bdf79f0507f65a392b0ab4667716BFE0110', // VaultRelayer
    maxUint256
  ]
})
The VaultRelayer address (0xC92E8bdf79f0507f65a392b0ab4667716BFE0110) is the same on all supported chains. Do not approve the Settlement contract (0x9008D19...) directly — it will not work.
FieldValue
HTTP Status400 Bad Request
Error CodeOrderExpired
Root CauseThe validTo timestamp on the order is in the past. This commonly happens when there is a delay between getting a quote and submitting the order.
Fix:
  • Request a fresh quote and submit promptly.
  • Increase the validity window by setting a later validTo timestamp (e.g., current time + 30 minutes).
  • Note that validTo is a Unix timestamp in seconds, not milliseconds.
FieldValue
HTTP Status400 Bad Request
Error CodeSellAmountOverflow or BuyAmountOverflow
Root CauseThe sell or buy amount exceeds the maximum value for uint256. This typically occurs when token decimals are mishandled (e.g., applying decimals twice).
Fix:
  • Verify you are converting human-readable amounts to the correct token decimals only once.
  • For a token with 18 decimals, 1.0 token = "1000000000000000000".
  • Amounts must be positive integer strings without decimal points.
FieldValue
HTTP Status400 Bad Request
Error CodeInvalidAppData
Root CauseThe appData bytes32 hash in the order does not match any previously uploaded appData document, or the appData content is malformed.
Fix:
  • Upload the appData JSON document first via PUT /api/v1/app_data/{hash} before submitting the order.
  • Ensure the appData field in the order is the keccak256 hash of the uploaded JSON document.
  • If using the SDK, appData is handled automatically. For direct API usage, follow the appData specification.
FieldValue
HTTP Status403 Forbidden
Error CodeForbidden
Root CauseThe order owner address has been flagged or banned from using CoW Protocol, typically due to policy violations.
Fix:
  • This is not a transient error. Contact the CoW Protocol team if you believe this is in error.
FieldValue
HTTP Status429 Too Many Requests
Error CodeRateLimited
Root CauseOrder submission rate limit exceeded. Submissions are limited to approximately 5 requests per second.
Fix:
  • Implement exponential backoff with jitter.
  • Batch order logic to avoid bursts.
  • See the Common Patterns section for retry strategy.

Settlement Errors

These are not API error responses. They occur after an order has been accepted into the orderbook, during the solver competition and on-chain settlement phase. Monitor order status via GET /api/v1/orders/{uid}.
FieldValue
Order Statusexpired
Root CauseSolvers could not find a profitable execution path before the order’s validTo timestamp. Common causes include tight slippage tolerance, illiquid token pairs, or rapidly moving markets.
Fix:
  • Widen slippage tolerance (e.g., from 0.5% to 1-2%).
  • Increase the validTo window to give solvers more time and more auction batches.
  • For illiquid pairs, consider using a limit order with a longer validity period.
  • Check that the buy/sell amounts are still within market range.
FieldValue
Order Statusexpired (with zero or no fills)
Root CauseThe order has partiallyFillable: false (the default), meaning it requires a complete fill. If solvers cannot match the full amount in a single batch, the order goes unfilled.
Fix:
  • Set partiallyFillable: true in the order to allow the order to be filled incrementally across multiple batches.
  • This is particularly useful for large orders relative to available liquidity.
FieldValue
Order Statuscancelled
Root CauseThe order was explicitly cancelled either by the user (via DELETE /api/v1/orders/{uid} or an on-chain cancellation) or by protocol policy.
Fix:
  • Check the cancellation source by querying GET /api/v1/orders/{uid} and inspecting the invalidated and onchainUser fields.
  • If the cancellation was unintentional, submit a new order.
  • On-chain cancellations are irreversible.

Common Patterns

HTTP Status Code Summary

StatusCategoryAction
200SuccessProcess response
400Client errorFix request parameters, do not retry without changes
403ForbiddenDo not retry, address is restricted
404Not foundVerify the order UID or endpoint path
429Rate limitedRetry with exponential backoff
500Server errorRetry with exponential backoff
For transient errors (429, 500), use exponential backoff with jitter:
async function fetchWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 5
): Promise<Response> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options)

    if (response.ok) return response

    // Do not retry client errors (except rate limits)
    if (response.status >= 400 && response.status < 500 && response.status !== 429) {
      throw new Error(`Client error ${response.status}: ${await response.text()}`)
    }

    // Exponential backoff with jitter
    const baseDelay = Math.min(1000 * Math.pow(2, attempt), 30000)
    const jitter = Math.random() * 1000
    await new Promise(resolve => setTimeout(resolve, baseDelay + jitter))
  }

  throw new Error(`Request failed after ${maxRetries} retries`)
}

Debugging Orders

When an order is not behaving as expected:
  1. Query the order status via GET /api/v1/orders/{uid} and inspect the status field (open, fulfilled, expired, cancelled).
  2. Check the explorer at https://explorer.cow.fi/orders/{uid} for a visual breakdown of order state, fills, and solver competition results.
  3. Verify on-chain state — confirm the owner has sufficient balance and the VaultRelayer has adequate allowance.
  4. Check solver competition via GET /api/v1/solver_competition/{auction_id} to see if solvers attempted to include the order and why they may have excluded it.
The CoW Explorer at explorer.cow.fi is the fastest way to diagnose order issues. Paste any order UID to see its full lifecycle, including solver attempts and settlement transactions.
Last modified on March 11, 2026