Overview
When integrating with CoW Protocol, errors can occur at four distinct stages of the order lifecycle:- Quoting — requesting a price quote from the API
- Signing — constructing and signing the order client-side
- Submission — posting the signed order to the orderbook
- Settlement — solver execution after the order is accepted
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 byPOST /api/v1/quote when requesting a price quote.
400 — SellAmountDoesNotCoverFee
400 — SellAmountDoesNotCoverFee
- Increase the
sellAmountBeforeFeeto 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.
400 — NoLiquidity
400 — NoLiquidity
- 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.
400 — UnsupportedToken
400 — UnsupportedToken
- 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.
400 — InvalidParameter
400 — InvalidParameter
- Ensure all required fields are present:
sellToken,buyToken,from,kind, and eithersellAmountBeforeFee(for sell orders) orbuyAmountAfterFee(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 thekindfield.
429 — RateLimited
429 — RateLimited
- Implement exponential backoff with jitter between retries.
- Respect
Retry-Afterheaders when present. - Cache quote responses where appropriate to reduce request volume.
- See the Common Patterns section for a recommended retry strategy.
500 — Internal Server Error
500 — Internal Server Error
- 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.Invalid domain separator — wrong chainId or verifyingContract
Invalid domain separator — wrong chainId or verifyingContract
chainId must match the network you are submitting to.TypedData signature mismatch — order struct doesn't match expected types
TypedData signature mismatch — order struct doesn't match expected types
signOrder helper which handles this automatically. See the signing schemes reference for full details.Wrong signer — signature doesn't match the from address
Wrong signer — signature doesn't match the from address
- Ensure the signer (private key or connected wallet) matches the
fromaddress used when requesting the quote. - When using a smart contract wallet (e.g., Safe), use the
presignsigning scheme instead ofeip712. - Double-check that you are not mixing up accounts in a multi-wallet setup.
Submission Errors
These errors are returned byPOST /api/v1/orders when submitting a signed order to the orderbook.
400 — InvalidSignature
400 — InvalidSignature
- Verify the
signingSchemefield 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/ownerfield. - If using
ethsign, remember the message is prefixed with\x19Ethereum Signed Message:\n32before hashing.
400 — DuplicatedOrder
400 — DuplicatedOrder
- 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, orappData) to produce a different UID.
400 — InsufficientBalance
400 — InsufficientBalance
- 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.
400 — InsufficientAllowance
400 — InsufficientAllowance
- 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.
400 — OrderExpired
400 — OrderExpired
- Request a fresh quote and submit promptly.
- Increase the validity window by setting a later
validTotimestamp (e.g., current time + 30 minutes). - Note that
validTois a Unix timestamp in seconds, not milliseconds.
400 — SellAmountOverflow / BuyAmountOverflow
400 — SellAmountOverflow / BuyAmountOverflow
- Verify you are converting human-readable amounts to the correct token decimals only once.
- For a token with 18 decimals,
1.0token ="1000000000000000000". - Amounts must be positive integer strings without decimal points.
400 — InvalidAppData
400 — InvalidAppData
- Upload the appData JSON document first via
PUT /api/v1/app_data/{hash}before submitting the order. - Ensure the
appDatafield 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.
403 — Forbidden
403 — Forbidden
- This is not a transient error. Contact the CoW Protocol team if you believe this is in error.
429 — RateLimited
429 — RateLimited
- 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 viaGET /api/v1/orders/{uid}.
Order expires without fill
Order expires without fill
- Widen slippage tolerance (e.g., from 0.5% to 1-2%).
- Increase the
validTowindow 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.
Partial fill not enabled
Partial fill not enabled
- Set
partiallyFillable: truein the order to allow the order to be filled incrementally across multiple batches. - This is particularly useful for large orders relative to available liquidity.
Order cancelled
Order cancelled
- Check the cancellation source by querying
GET /api/v1/orders/{uid}and inspecting theinvalidatedandonchainUserfields. - If the cancellation was unintentional, submit a new order.
- On-chain cancellations are irreversible.
Common Patterns
HTTP Status Code Summary
Recommended Retry Strategy
If you are calling the API directly, use exponential backoff with jitter for transient errors (429, 500).
Debugging Orders
When an order is not behaving as expected:- Query the order status via
GET /api/v1/orders/{uid}and inspect thestatusfield (open,fulfilled,expired,cancelled). - Check the explorer at
https://explorer.cow.fi/orders/{uid}for a visual breakdown of order state, fills, and solver competition results. - Verify on-chain state — confirm the owner has sufficient balance and the VaultRelayer has adequate allowance.
- 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.