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
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 byPOST /api/v1/quote when requesting a price quote.
400 — SellAmountDoesNotCoverFee
400 — SellAmountDoesNotCoverFee
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | SellAmountDoesNotCoverFee |
| Root Cause | The 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | NoLiquidity |
| Root Cause | No 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | UnsupportedToken |
| Root Cause | One 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | InvalidParameter |
| Root Cause | One 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 429 Too Many Requests |
| Error Code | RateLimited |
| Root Cause | You have exceeded the API rate limit. Quote requests are limited to approximately 10 requests per second. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 500 Internal Server Error |
| Error Code | InternalServerError |
| Root Cause | A transient error occurred on the API server. This is typically temporary and not caused by your request. |
- 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
| Field | Value |
|---|---|
| Error Type | Client-side / signature verification failure |
| Root Cause | The 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. |
| Chain | chainId | Settlement Contract |
|---|---|---|
| Ethereum | 1 | 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 |
| Gnosis Chain | 100 | 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 |
| Arbitrum One | 42161 | 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 |
| Base | 8453 | 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 |
| Sepolia | 11155111 | 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 |
The settlement contract address is the same across all supported chains, but the
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
| Field | Value |
|---|---|
| Error Type | Client-side / EIP-712 encoding error |
| Root Cause | The 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). |
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
| Field | Value |
|---|---|
| Error Type | Client-side / signer mismatch |
| Root Cause | The 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | InvalidSignature |
| Root Cause | The 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. |
- 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 — DuplicateOrder
400 — DuplicateOrder
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | DuplicateOrder |
| Root Cause | An order with the same UID already exists in the orderbook. Order UIDs are deterministic based on order parameters and the owner address. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | InsufficientBalance |
| Root Cause | The order owner’s wallet does not hold enough of the sell token to cover the sell amount plus fees. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | InsufficientAllowance |
| Root Cause | The 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | OrderExpired |
| Root Cause | The 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. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | SellAmountOverflow or BuyAmountOverflow |
| Root Cause | The sell or buy amount exceeds the maximum value for uint256. This typically occurs when token decimals are mishandled (e.g., applying decimals twice). |
- 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
| Field | Value |
|---|---|
| HTTP Status | 400 Bad Request |
| Error Code | InvalidAppData |
| Root Cause | The appData bytes32 hash in the order does not match any previously uploaded appData document, or the appData content is malformed. |
- 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
| Field | Value |
|---|---|
| HTTP Status | 403 Forbidden |
| Error Code | Forbidden |
| Root Cause | The order owner address has been flagged or banned from using CoW Protocol, typically due to policy violations. |
- This is not a transient error. Contact the CoW Protocol team if you believe this is in error.
429 — RateLimited
429 — RateLimited
| Field | Value |
|---|---|
| HTTP Status | 429 Too Many Requests |
| Error Code | RateLimited |
| Root Cause | Order submission rate limit exceeded. Submissions are limited to approximately 5 requests per second. |
- 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
| Field | Value |
|---|---|
| Order Status | expired |
| Root Cause | Solvers 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. |
- 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
| Field | Value |
|---|---|
| Order Status | expired (with zero or no fills) |
| Root Cause | The 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. |
- 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
| Field | Value |
|---|---|
| Order Status | cancelled |
| Root Cause | The order was explicitly cancelled either by the user (via DELETE /api/v1/orders/{uid} or an on-chain cancellation) or by protocol policy. |
- 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
| Status | Category | Action |
|---|---|---|
200 | Success | Process response |
400 | Client error | Fix request parameters, do not retry without changes |
403 | Forbidden | Do not retry, address is restricted |
404 | Not found | Verify the order UID or endpoint path |
429 | Rate limited | Retry with exponential backoff |
500 | Server error | Retry with exponential backoff |
Recommended Retry Strategy
For transient errors (429, 500), use exponential backoff with jitter:
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.
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.