Binance API error codes use negative integer encoding, ranging from -1000 to -2099. They are categorized into four main types: General Errors (-1000 to -1099), Request Errors (-1100 to -1199), Rate Limiting/Risk Control (-1003/-1013), and Order Errors (-2010 to -2099). This article compiles 80+ error codes encountered in real-world production environments along with their solutions and Python error-handling middleware snippets. Readers who haven't enabled API access should first complete KYC on the Binance Official Website; new users can Register for Free.
I. Error Response Structure
All Binance API error responses follow a unified format:
{
"code": -1021,
"msg": "Timestamp for this request is outside of the recvWindow."
}
The HTTP status code is typically 400 (Business Error) or 403/429/418 (Gateway Error).
II. General Errors (-1000 to -1099)
| Code | Message | Meaning | Solution |
|---|---|---|---|
| -1000 | UNKNOWN | Unknown error | Retry; if it persists, contact support. |
| -1001 | DISCONNECTED | Internal server disconnection | Wait 5s and retry. |
| -1002 | UNAUTHORIZED | Unauthorized | Check the X-MBX-APIKEY header. |
| -1003 | TOO_MANY_REQUESTS | Rate limit exceeded | Wait for the number of seconds in Retry-After. |
| -1006 | UNEXPECTED_RESP | Unexpected response | Retry. |
| -1007 | TIMEOUT | Request timeout | Increase recvWindow. |
| -1014 | UNKNOWN_ORDER_COMPOSITION | Unsupported order composition | Check the order type. |
| -1015 | TOO_MANY_ORDERS | Order count limit exceeded | Cancel some open orders. |
| -1016 | SERVICE_SHUTTING_DOWN | Service shutting down | Wait for recovery. |
| -1020 | UNSUPPORTED_OPERATION | Unsupported operation | Consult the documentation. |
| -1021 | INVALID_TIMESTAMP | Timestamp offset error | Sync with NTP or increase recvWindow. |
| -1022 | INVALID_SIGNATURE | Invalid signature | Check the signature algorithm. |
Detailed Explanation of Key Errors
-1003 TOO_MANY_REQUESTS:
{"code": -1003, "msg": "Too many requests; current limit is 6000 request weight per 1 MINUTE. Please use WebSocket Streams for live updates to avoid polling the API."}
Handling:
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
# Retry afterwards
-1021 INVALID_TIMESTAMP:
{"code": -1021, "msg": "Timestamp for this request is outside of the recvWindow."}
Handling:
# Option 1: Sync server time difference
server_time = requests.get("https://api.binance.com/api/v3/time").json()["serverTime"]
local_time = int(time.time() * 1000)
offset = server_time - local_time # Save and add to every signature
# Option 2: Increase recvWindow (max 60000)
params["recvWindow"] = 10000
-1022 INVALID_SIGNATURE:
{"code": -1022, "msg": "Signature for this request is not valid."}
Common causes:
- The order of parameters in the signature string and request string is inconsistent.
- Numeric parameters are enclosed in quotes.
- The Secret Key is truncated or contains spaces.
- Different URL encoding methods are used.
III. Parameter Errors (-1100 to -1199)
| Code | Message | Meaning | Solution |
|---|---|---|---|
| -1100 | ILLEGAL_CHARS | Illegal characters in parameters | Clean the input. |
| -1101 | TOO_MANY_PARAMETERS | Too many parameters | Streamline parameters. |
| -1102 | MANDATORY_PARAM_EMPTY_OR_MALFORMED | Mandatory parameter missing/malformed | Check API documentation. |
| -1103 | UNKNOWN_PARAM | Unknown parameter | Remove unnecessary fields. |
| -1104 | UNREAD_PARAMETERS | Unused parameters | Remove redundant parameters. |
| -1105 | PARAM_EMPTY | Parameter is empty | Enter a valid value. |
| -1106 | PARAM_NOT_REQUIRED | Parameter not required | Remove it. |
| -1111 | BAD_PRECISION | Precision error | Must comply with LOT_SIZE / PRICE_FILTER. |
| -1112 | NO_DEPTH | Order book is empty | Wait for market recovery. |
| -1114 | TIF_NOT_REQUIRED | TIF not applicable | Do not pass timeInForce for market orders. |
| -1115 | INVALID_TIF | Invalid TIF | Use GTC / IOC / FOK. |
| -1116 | INVALID_ORDER_TYPE | Invalid order type | Check supported types. |
| -1117 | INVALID_SIDE | Invalid side | Use BUY or SELL. |
| -1118 | EMPTY_NEW_CL_ORD_ID | Empty client order ID | Provide newClientOrderId or omit it. |
| -1119 | EMPTY_ORG_CL_ORD_ID | Empty original order ID | Provide orderId when canceling/querying. |
| -1120 | BAD_INTERVAL | Invalid K-line interval | Use 1m/5m/15m/1h/4h/1d etc. |
| -1121 | BAD_SYMBOL | Invalid trading pair | Call exchangeInfo to verify. |
| -1125 | INVALID_LISTEN_KEY | Invalid listenKey | Call userDataStream again. |
| -1127 | MORE_THAN_XX_HOURS | Query time span exceeded | Use multiple queries instead. |
| -1128 | OPTIONAL_PARAMS_BAD_COMBO | Invalid optional parameter combo | Check documentation for mutual exclusivity. |
| -1130 | INVALID_PARAMETER | Invalid parameter value | Correct the value range. |
| -1131 | INVALID_JSON | Invalid JSON format | Validate the JSON. |
Detailed Explanation of Key Errors
-1111 BAD_PRECISION (Extremely common):
Filter failure: LOT_SIZE
Cause: The quantity or price does not comply with the stepSize or tickSize of the trading pair.
# Correct approach: Round after querying trading rules
import math
def get_filters(symbol: str) -> dict:
r = requests.get("https://api.binance.com/api/v3/exchangeInfo",
params={"symbol": symbol}).json()
return {f["filterType"]: f for f in r["symbols"][0]["filters"]}
def round_step(value: float, step: float) -> float:
return math.floor(value / step) * step
filters = get_filters("BTCUSDT")
step_size = float(filters["LOT_SIZE"]["stepSize"]) # 0.00001
tick_size = float(filters["PRICE_FILTER"]["tickSize"]) # 0.01
min_notional = float(filters["NOTIONAL"]["minNotional"]) # 5.0
# Normalize before placing an order
quantity = round_step(0.0015789, step_size) # → 0.00157
price = round_step(60123.4567, tick_size) # → 60123.45
IV. Filter Failures (-1013)
-1013 INVALID_MESSAGE provides specific reasons through various filter types:
| Filter Type | Meaning | Solution |
|---|---|---|
| PRICE_FILTER | Price does not comply with tickSize | Round according to tickSize. |
| LOT_SIZE | Quantity does not comply with stepSize | Round according to stepSize. |
| MIN_NOTIONAL | Total order value is too low (<5 USDT) | Increase the quantity. |
| NOTIONAL | Notional value is incorrect | Same as MIN_NOTIONAL. |
| PERCENT_PRICE | Price deviation is too large | Adjust closer to market price. |
| MARKET_LOT_SIZE | Market order quantity is incorrect | Comply with market order rules. |
| MAX_NUM_ORDERS | Max open orders for pair exceeded | Cancel existing orders before placing new ones. |
| MAX_NUM_ALGO_ORDERS | Algo order limit exceeded | Cancel some stop-loss/take-profit orders. |
V. Order Errors (-2010 to -2099)
| Code | Message | Meaning | Solution |
|---|---|---|---|
| -2010 | NEW_ORDER_REJECTED | New order rejected | Check the specific msg. |
| -2011 | CANCEL_REJECTED | Cancel rejected | Order may have already been filled. |
| -2013 | NO_SUCH_ORDER | Order does not exist | Check the orderId. |
| -2014 | BAD_API_KEY_FMT | Bad API Key format | Verify the 64-character length. |
| -2015 | REJECTED_MBX_KEY | Key/IP/Permission error | Check whitelist and permissions. |
| -2016 | NO_TRADING_WINDOW | No trading window | Trading pair is suspended. |
| -2018 | BALANCE_NOT_SUFFICIENT | Insufficient balance | Deposit funds or reduce quantity. |
| -2019 | MARGIN_NOT_SUFFICIENT | Insufficient margin | Lower leverage or add margin. |
| -2020 | UNABLE_TO_FILL | Unable to fill | Adjust limit order price. |
| -2021 | ORDER_WOULD_IMMEDIATELY_TRIGGER | Order would trigger immediately | Adjust stop/take-profit price. |
| -2022 | REDUCE_ONLY_REJECT | Reduce Only rejected | Check position direction. |
| -2023 | USER_IN_LIQUIDATION | User in liquidation | Wait for liquidation to finish. |
| -2024 | POSITION_NOT_SUFFICIENT | Insufficient position | Cannot close this much. |
| -2025 | MAX_OPEN_ORDER_EXCEEDED | Max open orders exceeded | Cancel some old orders. |
| -2026 | REDUCE_ONLY_ORDER_TYPE_NOT_SUPPORTED | Type doesn't support Reduce Only | Switch to Market or Limit. |
| -2027 | MAX_LEVERAGE_RATIO | Max leverage exceeded | Lower the leverage. |
| -2028 | MIN_LEVERAGE_RATIO | Leverage too low | Increase the leverage. |
Detailed Explanation of Key Errors
-2010 NEW_ORDER_REJECTED (Most Common):
The msg field will provide the specific reason:
"Account has insufficient balance for requested action"→ Insufficient balance."Order would immediately match and take"→ Limit order would match immediately (in LIMIT_MAKER mode)."Filter failure: LOT_SIZE"→ Quantity does not match step size."Filter failure: PERCENT_PRICE"→ Price deviation is too large.
def place_order_safely(symbol, side, qty, price):
try:
return client.create_order(
symbol=symbol, side=side, type="LIMIT",
timeInForce="GTC", quantity=qty, price=price
)
except BinanceAPIException as e:
if e.code == -2010:
if "insufficient balance" in e.message:
return {"error": "Insufficient balance"}
if "Filter failure: LOT_SIZE" in e.message:
return {"error": "Quantity precision error, must round to stepSize"}
raise
-2015 REJECTED_MBX_KEY:
Three sub-causes (infer from the error message):
- Bad API Key format: Check for 64-character length.
- IP not on whitelist: Log in to Binance and update.
- Permissions not enabled: e.g., calling
/fapi/without checking "Enable Futures".
VI. Risk Control Related Errors
| Code | Message | Meaning | Solution |
|---|---|---|---|
| -4001 | PRICE_LESS_THAN_ZERO | Negative price | Check parameters. |
| -4002 | PRICE_GREATER_THAN_MAX_PRICE | Price exceeds upper limit | Lower the price. |
| -4003 | QTY_LESS_THAN_ZERO | Negative quantity | Change to a positive value. |
| -4004 | QTY_LESS_THAN_MIN_QTY | Quantity below minimum | Refer to LOT_SIZE. |
| -4005 | QTY_GREATER_THAN_MAX_QTY | Quantity exceeds upper limit | Place orders in batches. |
| -4006 | STOP_PRICE_LESS_THAN_ZERO | Negative stop price | Correct the value. |
| -4164 | MIN_NOTIONAL | Notional amount below 5 USDT | Increase quantity. |
| -5021 | FOK_ORDER_REJECT | FOK order rejected | Insufficient liquidity; use GTC instead. |
| -5022 | GTX_ORDER_REJECT | GTX (Post Only) rejected | Market price changed; price is no longer a maker. |
VII. Unified Error Handling Middleware (Python)
import time
import requests
from typing import Optional
class BinanceAPIError(Exception):
def __init__(self, code: int, msg: str, raw: dict):
self.code = code
self.msg = msg
self.raw = raw
super().__init__(f"Binance {code}: {msg}")
def handle_response(response: requests.Response) -> dict:
data = response.json()
if "code" in data and data["code"] < 0:
raise BinanceAPIError(data["code"], data.get("msg", ""), data)
return data
def request_with_recovery(method, url, **kwargs) -> Optional[dict]:
for attempt in range(5):
try:
r = requests.request(method, url, **kwargs)
if r.status_code == 429:
retry_after = int(r.headers.get("Retry-After", 60))
print(f"Rate limited, waiting {retry_after}s")
time.sleep(retry_after)
continue
if r.status_code == 418:
raise SystemExit("IP banned, program terminated")
data = handle_response(r)
return data
except BinanceAPIError as e:
if e.code == -1021:
print("Timestamp offset, resyncing")
# Sync time and retry
continue
if e.code in (-1001, -1006, -1007):
wait = 2 ** attempt
print(f"Temporary error {e.code}, retrying in {wait}s")
time.sleep(wait)
continue
# Business errors that cannot be retried are raised directly
raise
return None
VIII. Common Questions FAQ
Q1: What should I do if error code -1021 appears repeatedly?
A: It's a system clock issue. On Linux, enable chronyd:
sudo systemctl enable chronyd
sudo chronyc sources -v # Verify sync sources
On Windows, go to Control Panel → Date and Time → Internet Time → Sync with time.windows.com.
Q2: What causes -1015 TOO_MANY_ORDERS?
A: The number of unfilled open orders for a single trading pair has exceeded 200 (Spot) or the limit set by the MAX_NUM_ORDERS filter. Simply cancel some distant orders.
Q3: I've checked permissions and IP for -2015, but it still errors. Why?
A: Check if you're using a Spot Key on a Futures domain (fapi.binance.com) or vice-versa. Spot and Futures require different permission bits; even if you have a key, it won't work for contract interfaces if "Enable Futures" isn't checked.
Q4: How can I log all error codes?
A: Wrap a middleware layer to count by error code:
from collections import Counter
error_counter = Counter()
def log_error(code: int):
error_counter[code] += 1
if error_counter[code] > 100:
alert(f"Error {code} occurred {error_counter[code]} times, possible system issue")
Q5: What is the difference between -1013 and -2010?
A: -1013 is a filter error (parameters do not meet trading rules), whereas -2010 is an order rejection (rejected at the business layer, reason in msg). -1013 can usually be avoided by pre-calculating on the client side, while -2010 depends more on real-time market states (balance, slippage, risk control).
After reviewing the error code list, return to the [Category Navigation](/en/vault/API Integration/) to explore other technical topics under "API Integration".