Binance Lot Size Error: Fix It Fast and Trade Smarter
Hit a lot size error on Binance? Learn what causes it, how to fix it, and how to write order logic that never breaks on Binance or any other exchange.
Hit a lot size error on Binance? Learn what causes it, how to fix it, and how to write order logic that never breaks on Binance or any other exchange.
You've got your order logic wired up, your API keys are live, and then — boom. Binance rejects your order with a cryptic message about lot size. It's one of the most common walls new algo traders and bot builders hit, and it's almost never explained well in the official docs. The Binance lot size error isn't a bug in your code — it's a filter Binance enforces on every trading pair, and once you understand how it works, you'll never get tripped up by it again.
Every trading pair on Binance has a set of filters that govern what constitutes a valid order. The LOT_SIZE filter is one of the most important. It defines three things: the minimum quantity you can trade (minQty), the maximum quantity you can trade (maxQty), and the step size — the increment your order quantity must conform to. If your order quantity doesn't fit neatly into these constraints, Binance rejects it outright.
For example, on the BTCUSDT pair the step size might be 0.00001 BTC. That means your order quantity must be a multiple of 0.00001 — values like 0.000013 will fail. On smaller altcoins traded on Binance US, the step sizes can be entirely different, and deposit limits on Binance US can also affect how much capital you're working with when sizing orders. This is where traders using automated systems start running into walls.
The LOT_SIZE filter is pair-specific. Don't hardcode step sizes — always pull them dynamically from the Binance exchangeInfo endpoint before placing orders.
When Binance rejects an order due to a quantity issue, the API returns error code -1013 with a message like 'Filter failure: LOT_SIZE'. This is the raw Binance API error lot_size response, and it means your order quantity violates at least one of the three filter constraints. The most common culprits are floating point precision issues — your code calculated 0.01230000000000001 BTC instead of 0.0123 BTC, and Binance isn't going to round it for you.
Platforms like Bybit and OKX handle rounding more gracefully in their APIs, silently truncating quantities to valid increments. Binance takes a stricter approach: you must send a valid quantity or the order won't go through. This isn't necessarily worse — it's more predictable once you know the rules — but it does require you to handle rounding explicitly in your order logic.
import math
from binance.client import Client
client = Client(api_key, api_secret)
def get_lot_size_filter(symbol):
info = client.get_symbol_info(symbol)
for f in info['filters']:
if f['filterType'] == 'LOT_SIZE':
return {
'minQty': float(f['minQty']),
'maxQty': float(f['maxQty']),
'stepSize': float(f['stepSize'])
}
return None
def round_to_step(quantity, step_size):
# Use math.floor to avoid floating point overshoot
precision = int(round(-math.log(step_size, 10)))
return math.floor(quantity / step_size) * step_size
symbol = 'BTCUSDT'
filter_info = get_lot_size_filter(symbol)
step = filter_info['stepSize']
raw_qty = 0.01234567
valid_qty = round_to_step(raw_qty, step)
print(f'Valid quantity: {valid_qty}') # 0.01234
The key insight in that snippet is using math.floor rather than round(). Rounding up can push your quantity over a valid step boundary or exceed your available balance. Floor always keeps you safe on the lower side.
Before you write a single line of order logic, you should know how to query Binance's exchange info. The /api/v3/exchangeInfo endpoint returns every active trading pair along with all its filters. You can call this once at startup and cache the results rather than hitting it on every order.
import requests
def fetch_exchange_filters(symbol):
url = 'https://api.binance.com/api/v3/exchangeInfo'
response = requests.get(url, params={'symbol': symbol})
data = response.json()
filters = {}
for sym in data['symbols']:
if sym['symbol'] == symbol:
for f in sym['filters']:
filters[f['filterType']] = f
return filters
filters = fetch_exchange_filters('ETHUSDT')
lot = filters['LOT_SIZE']
print(f"Min: {lot['minQty']}, Max: {lot['maxQty']}, Step: {lot['stepSize']}")
For traders running bots across multiple venues simultaneously — say, Binance for BTC majors and KuCoin or Gate.io for smaller altcoins — the pattern is the same but each exchange has its own API endpoint and filter naming convention. Building a unified filter-fetching layer early saves a lot of debugging time later.
| Exchange | Filter Name | Rounding Behavior | Min Order (BTC) | API Docs Quality |
|---|---|---|---|---|
| Binance | LOT_SIZE | Strict — rejects invalid qty | 0.00001 | Comprehensive |
| Bybit | lotSizeFilter | Tolerant — auto-truncates | 0.001 | Good |
| OKX | lotSz | Tolerant — auto-truncates | 0.00001 | Good |
| KuCoin | baseIncrement | Strict — rejects | 0.00001 | Moderate |
| Gate.io | amount_precision | Strict — rejects | 0.0001 | Moderate |
| Coinbase Advanced | base_increment | Strict — rejects | 0.000001 | Good |
Bybit and OKX being more forgiving is convenient when you're prototyping, but don't let it create sloppy habits. When you move to Binance — which most serious algo traders end up doing because of its liquidity depth — those silent truncations become hard rejections. Build the rounding logic right from the start.
If you're trading on Binance US rather than global Binance, there's an additional layer of friction worth knowing about: the Binance US deposit limit. Depending on your verification tier, daily fiat deposit limits can range from $5,000 on basic accounts up to $500,000 or more for fully verified users. This isn't directly related to the lot size filter, but it affects how much capital you're working with — and if you're sizing orders as a percentage of your available balance, a lower-than-expected balance from deposit delays can cause your calculated quantities to fall below minQty.
The fix is simple: always check your actual available balance via the API before calculating order size, not just your expected balance. And always validate the calculated quantity against minQty before submitting — throw a meaningful error or skip the order if the sizing logic produces something below the minimum.
Always guard against sub-minimum orders in your bot logic. A rejected order is recoverable — a bot that silently fails to enter a position at a key signal moment is not.
Getting your order sizing right is only half the equation. The other half is knowing when to trade. Tools like VoiceOfChain provide real-time order flow signals derived from live exchange data — whale accumulation patterns, imbalance signals, breakout alerts — that you can feed into your bot's entry logic. When a signal fires, your bot needs to respond fast and correctly, which means your lot size calculation has to work every single time without manual intervention.
A common pattern among algo traders using VoiceOfChain is to pre-calculate valid order sizes for likely signal scenarios — rounding them to valid step sizes for Binance, Bybit, or whichever venue they're trading — and then submit the order immediately when the signal threshold is crossed. This eliminates the latency of doing API lookups at signal time and ensures the quantity is always valid.
The Binance lot size error is one of those obstacles that feels frustrating the first time you hit it and trivial once you understand the underlying system. Binance enforces strict quantity filters because precision matters at scale — both for their matching engine and for your execution quality. Build the rounding logic once, build it correctly, and you'll never see -1013 again. More importantly, your bot will execute cleanly when it matters — when a real signal fires and every millisecond counts.
Whether you're running a simple DCA bot on Binance, arbitraging across Binance and Coinbase, or feeding signals from VoiceOfChain into an automated strategy on Bybit or OKX, the same discipline applies: always validate before you submit, always pull live filter data rather than hardcoding values, and always handle the edge cases your happy path doesn't exercise.