Skip to main content

Debugging Programmatic Orders

Use this decision tree when your programmatic order isn’t executing as expected.

Why didn’t my order execute?

Order not executing
├── Is the tx confirmed on-chain?
│   └── No → Wait for confirmation or check if tx reverted
├── Does the order appear in CoW Explorer?
│   └── No → Watch-tower hasn't indexed it (see below)
├── Is the order status "open"?
│   ├── "presignaturePending" → PreSign tx not yet confirmed
│   ├── "cancelled" → Order was cancelled (check who/when)
│   └── "expired" → validTo passed before a solver could fill it
└── Order is "open" but not filling
    ├── Is the Safe balance sufficient?
    ├── Is the VaultRelayer approved?
    ├── Is getTradeableOrder() reverting?
    └── Are solvers finding it unprofitable? (check competition)

Step 1: Check the transaction

Verify the ComposableCoW.create() transaction was confirmed:
  • Check the tx hash on Etherscan/block explorer
  • Look for the ConditionalOrderCreated event in the logs
  • If the tx reverted, check the revert reason (usually setup issues — see Troubleshooting)

Step 2: Check watch-tower indexing

The watch-tower monitors on-chain events and posts discrete orders to the orderbook. Is the public watch-tower monitoring your chain? Supported: Ethereum, Gnosis Chain, Arbitrum One, Base, Polygon, Avalanche, Lens, BNB Chain, Linea, Plasma, Ink, Sepolia Check via the watch-tower API: If you’re running your own watch-tower:
# Dump the database to see all indexed orders
curl http://localhost:8080/api/dump/<CHAIN_ID>
Look for your Safe address in the output. If it’s not there, the watch-tower hasn’t seen the ConditionalOrderCreated event yet. Run a one-shot check:
LOG_LEVEL=DEBUG yarn cli run \
  --only-owner <YOUR_SAFE_ADDRESS> \
  --one-shot \
  --dry-run
This will show exactly what the watch-tower sees for your Safe and what orders it would post.

Step 3: Check getTradeableOrder()

The watch-tower calls your handler’s getTradeableOrder() function each polling cycle. If it reverts, no order is posted. Test it manually:
cast call <HANDLER_ADDRESS> \
  "getTradeableOrder(address,address,bytes32,bytes,bytes)(tuple)" \
  <SAFE_ADDRESS> \
  <SAFE_ADDRESS> \
  <CONDITIONAL_ORDER_PARAMS_HASH> \
  <STATIC_INPUT> \
  <OFF_CHAIN_INPUT>
Common revert reasons:
RevertCauseFix
OrderNotValidTime condition not met (e.g., TWAP part not started)Wait for the next time window
InsufficientBalanceSafe doesn’t hold enough sell tokensFund the Safe
SwapGuardRestrictionA swap guard is blocking the orderCheck guard conditions
Custom revertHandler-specific validation failedCheck your handler’s logic

Step 4: Check order status

Once the watch-tower posts an order, query its status:
curl https://api.cow.fi/mainnet/api/v1/orders/<ORDER_UID>
StatusMeaningAction
openOrder is in the orderbook, waiting for solversCheck if balance/allowance is sufficient
fulfilledOrder was filledSuccess
expiredvalidTo passed without fillWiden slippage or increase validity
cancelledOrder was cancelledCheck if it was intentional
presignaturePendingWaiting for on-chain pre-signatureOnly applies to PreSign, not ERC-1271

Step 5: Check solver competition

If the order is open but not filling:
# Get the latest auction to see if your order was included
curl https://api.cow.fi/mainnet/api/v1/auction
Solvers may skip your order if:
  • Insufficient balance at settlement time
  • Insufficient allowance for VaultRelayer
  • Unprofitable — the trade doesn’t generate enough surplus to cover gas
  • Illiquid pair — no good routing available

Common patterns

TWAP order only partially executing

TWAP orders execute in parts over time. Each part has its own time window. If a part doesn’t execute:
  • The time window may be too short for solvers to find it
  • The part amount may be too small to be profitable
  • The Safe may not have enough balance for the remaining parts

Order works on mainnet but not testnet

Sepolia has limited solver participation. See the testing guide for testnet-specific advice.

Order executes once but not again

For recurring orders (like TWAP), the watch-tower must post new discrete orders for each part. Check:
  • Is the watch-tower still running?
  • Has the programmatic order been cancelled on-chain?
  • Has the Safe’s balance been depleted?
Last modified on March 12, 2026