Debugging Programmatic Orders
Use this decision tree when your programmatic order isn’t executing as expected.Why didn’t my order execute?
Step 1: Check the transaction
Verify theComposableCoW.create() transaction was confirmed:
- Check the tx hash on Etherscan/block explorer
- Look for the
ConditionalOrderCreatedevent 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:ConditionalOrderCreated event yet.
Run a one-shot check:
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:
| Revert | Cause | Fix |
|---|---|---|
OrderNotValid | Time condition not met (e.g., TWAP part not started) | Wait for the next time window |
InsufficientBalance | Safe doesn’t hold enough sell tokens | Fund the Safe |
SwapGuardRestriction | A swap guard is blocking the order | Check guard conditions |
| Custom revert | Handler-specific validation failed | Check your handler’s logic |
Step 4: Check order status
Once the watch-tower posts an order, query its status:| Status | Meaning | Action |
|---|---|---|
open | Order is in the orderbook, waiting for solvers | Check if balance/allowance is sufficient |
fulfilled | Order was filled | Success |
expired | validTo passed without fill | Widen slippage or increase validity |
cancelled | Order was cancelled | Check if it was intentional |
presignaturePending | Waiting for on-chain pre-signature | Only applies to PreSign, not ERC-1271 |
Step 5: Check solver competition
If the order isopen but not filling:
- 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?
Related resources
- Troubleshooting — Setup issues (fallback handler, domain verifier)
- Watch Tower: Running Locally — Debug with your own watch-tower
- Error Reference — API error codes and fixes