Your grid bot compiled, authenticated, and then failed on the first order? This troubleshooting guide maps the most common crypto trading bot errors — Binance API codes, order rejections, rate limits, and runtime crashes — to concrete fixes with copy-paste Python snippets.
Series context: Companion to the trading bot build series. If you have not completed setup yet, start with Python setup, Binance API authentication, and grid trading implementation.
Quick Diagnostic Flow
Work through these checks in order — most failures resolve at step 1 or 2:
- Environment: Is
BINANCE_TESTNETset correctly for your key type? - Permissions: Does the API key have Spot Trading enabled?
- Network: Is your IP whitelisted (if restriction is enabled)?
- Clock: Is system time synced (fixes
-1021)? - Filters: Are price/qty rounded to exchange step sizes?
- Balance: Is there enough USDT/BTC for the full grid?
# Run this first — surfaces 80% of setup issues
python scripts/debug_grid.pyAuthentication Errors
Invalid API-key, IP, or permissions for action (-2015)
Cause: Wrong key type, missing permission, or IP not whitelisted.
Fix:
- Testnet keys require
exchange.set_sandbox_mode(True)— see the API configuration guide - Enable Enable Spot & Margin Trading when creating the key
- If IP restriction is on, add your server/VPS IP or disable restriction for testing
- Never reuse a key created on testnet.binance.vision on live api.binance.com
import ccxt, os
from dotenv import load_dotenv
load_dotenv()
exchange = ccxt.binance({
'apiKey': os.getenv('BINANCE_API_KEY'),
'secret': os.getenv('BINANCE_SECRET_KEY'),
})
if os.getenv('BINANCE_TESTNET', 'true').lower() == 'true':
exchange.set_sandbox_mode(True)
try:
exchange.fetch_balance()
print('✅ Authentication OK')
except Exception as e:
print(f'❌ Auth failed: {e}')Timestamp for this request is outside of the recvWindow (-1021)
Cause: Local clock drift — common on VPS and Docker containers.
Fix:
# Linux/macOS — sync clock
sudo ntpdate pool.ntp.org
# Or increase recvWindow in ccxt (temporary workaround)
exchange.options['recvWindow'] = 10000 # 10 secondsOrder Placement Errors
Filter failure: LOT_SIZE / MIN_NOTIONAL / PRICE_FILTER (-1013)
Cause: Price or quantity does not match exchange precision rules.
Fix: Normalize before every order. Full implementation in the grid trading guide (normalize_order() function).
# Quick check — print market filters
exchange.load_markets()
market = exchange.market('BTC/USDT')
print(market['precision']) # {'amount': 1e-05, 'price': 0.01}
print(market['limits']) # min amount, min costAccount has insufficient balance (-2010)
Cause: Grid requires both USDT (for buys) and BTC (for sells). Underestimating either side is the #1 capital error.
Fix:
# Calculate required capital before placing grid
center = exchange.fetch_ticker('BTC/USDT')['last']
spacing, levels, qty = 0.005, 10, 0.001
usdt_needed = sum(center * (1 - spacing * i) * qty for i in range(1, levels + 1))
btc_needed = levels * qty
print(f'Need: ${usdt_needed:.2f} USDT + {btc_needed:.4f} BTC')Reduce levels or qty until the calculation fits your balance.
Order would immediately match and take (-2010 variant)
Cause: Limit price crosses the spread (buy price ≥ best ask).
Fix: Set buy limits below current bid and sell limits above current ask. Re-fetch ticker before placing initial grid.
Rate Limit and Connection Errors
HTTP 429 / Way too many requests
Cause: Exceeding Binance request weight (1200/min for most endpoints).
Fix:
exchange = ccxt.binance({
'enableRateLimit': True, # REQUIRED — auto-throttles requests
})
# Add delay between grid order placements
import time
for level in grid_levels:
exchange.create_limit_order(...)
time.sleep(0.1) # 100ms between ordersConnection timeout / NetworkError
Cause: Unstable network or exchange maintenance.
Fix: Wrap API calls with retry logic:
import time
def retry_api(func, max_retries=3, delay=2):
for attempt in range(max_retries):
try:
return func()
except (ccxt.NetworkError, ccxt.RequestTimeout) as e:
if attempt == max_retries - 1:
raise
print(f'Retry {attempt + 1}/{max_retries}: {e}')
time.sleep(delay * (attempt + 1))Runtime and Logic Errors
Bot stops after first fill
Cause: Fill detection treats cancelled orders as fills, or exception in _process_filled_order() silently kills the loop.
Fix:
- Confirm fill status:
order['status'] == 'closed' and order['filled'] > 0 - Wrap the main loop in try/except and log full tracebacks
- Check logs:
tail -f data/logs/grid_trading_bot.log
Duplicate orders / grid drift
Cause: Bot restarted without checking existing open orders, placing a second grid on top.
Fix: On startup, fetch open orders and reconcile:
def reconcile_on_startup(exchange, symbol):
existing = exchange.fetch_open_orders(symbol)
if existing:
print(f'⚠️ {len(existing)} open orders found — cancel or adopt before starting')
for o in existing:
print(f" {o['side']} {o['amount']} @ {o['price']} id={o['id']}")
return existingModuleNotFoundError / ImportError
Cause: Virtual environment not activated or missing dependency.
Fix:
source crypto_trading_env/bin/activate
pip install -r requirements.txt
python -c "import ccxt; print(ccxt.__version__)"See the Python setup guide for the full project layout and dependency list.
Strategy-Specific Issues
Grid profitable in backtest, losing live
- Backtest used unrealistic fill assumptions (instant fills at limit price)
- Live fees higher than modeled (taker vs maker)
- Market shifted from ranging to trending — grid accumulates inventory
Fix: Re-run with the backtesting framework using conservative slippage (0.05%) and taker fees. Then paper trade for 30 days.
Mean reversion / trend bot overtrades
Cause: Signal fires every loop iteration without position tracking.
Fix: Add position state (self.in_position) and cooldown period. See the additional strategies guide for correct patterns.
Troubleshooting Checklist
- ✅ Virtual environment activated and dependencies installed?
- ✅
BINANCE_TESTNETmatches key type (testnet vs live)? - ✅ API key has Spot Trading permission?
- ✅ IP whitelist includes current server IP?
- ✅ System clock synced (no
-1021)? - ✅ Price/qty normalized to LOT_SIZE and MIN_NOTIONAL?
- ✅ Sufficient USDT + BTC for full grid?
- ✅
enableRateLimit: Truein ccxt config? - ✅ No duplicate open orders from previous run?
- ✅ Logs show full error tracebacks (not silent except)?
When to Escalate
If the checklist passes but orders still fail:
- Test the exact same call in Binance API test console (testnet)
- Compare raw request/response with
exchange.verbose = True - Check Binance system status for maintenance
- Try a different trading pair (ETH/USDT) to isolate symbol-specific filter issues
Next Steps
Once errors are resolved, continue the series:
- Python setup for crypto trading bots
- Binance API configuration and authentication
- Grid trading strategy implementation
- Additional trading strategies
Production path:
- Crypto bot backtesting framework
- Paper trading implementation
- Risk management and logging
- Series overview: How to build a cryptocurrency trading bot
Most bot failures are configuration issues, not strategy bugs. Fix the setup once, and the same patterns apply to every strategy you add.
Resolved your errors? Continue with backtesting to validate strategy performance before risking capital.
Comments