Los códigos de error de la API de Binance utilizan una codificación de enteros negativos que va desde el -1000 hasta el -2099. Se dividen en cuatro categorías principales: errores generales (-1000 ~ -1099), errores de solicitud (-1100 ~ -1199), límites de frecuencia/control de riesgo (-1003/-1013) y errores de órdenes (-2010 ~ -2099). Este artículo recopila más de 80 códigos de error encontrados en entornos de producción reales junto con sus soluciones y ejemplos de código middleware para el manejo de errores en Python. Si aún no ha habilitado su API, complete primero el KYC en el sitio oficial de Binance; los nuevos usuarios pueden registrarse gratis aquí.
I. Estructura de respuesta de error
Todas las respuestas de error de la API de Binance tienen un formato uniforme:
{
"code": -1021,
"msg": "Timestamp for this request is outside of the recvWindow."
}
El código de estado HTTP suele ser 400 (error de negocio) o 403/429/418 (error de puerta de enlace).
II. Errores generales (-1000 a -1099)
| Código | Mensaje | Significado | Solución |
|---|---|---|---|
| -1000 | UNKNOWN | Error desconocido | Reintentar; si persiste, contactar soporte |
| -1001 | DISCONNECTED | Desconexión interna del servidor | Esperar 5s y reintentar |
| -1002 | UNAUTHORIZED | No autorizado | Revisar el encabezado X-MBX-APIKEY |
| -1003 | TOO_MANY_REQUESTS | Límite de frecuencia excedido | Esperar según el encabezado Retry-After |
| -1006 | UNEXPECTED_RESP | Respuesta inesperada | Reintentar |
| -1007 | TIMEOUT | Tiempo de espera agotado | Aumentar el recvWindow |
| -1014 | UNKNOWN_ORDER_COMPOSITION | Composición de orden desconocida | Revisar el tipo de orden |
| -1015 | TOO_MANY_ORDERS | Demasiadas órdenes | Cancelar algunas órdenes abiertas |
| -1016 | SERVICE_SHUTTING_DOWN | Servicio cerrándose | Esperar a que se restablezca |
| -1020 | UNSUPPORTED_OPERATION | Operación no admitida | Consultar la documentación |
| -1021 | INVALID_TIMESTAMP | Marca de tiempo inválida | Sincronizar NTP o aumentar recvWindow |
| -1022 | INVALID_SIGNATURE | Firma inválida | Revisar el algoritmo de firma |
Detalles de errores clave
-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."}
Manejo:
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
# Reintentar después
-1021 INVALID_TIMESTAMP:
{"code": -1021, "msg": "Timestamp for this request is outside of the recvWindow."}
Manejo:
# Opción 1: Sincronizar la diferencia de tiempo con el servidor
server_time = requests.get("https://api.binance.com/api/v3/time").json()["serverTime"]
local_time = int(time.time() * 1000)
offset = server_time - local_time # Guardar y sumar en cada firma
# Opción 2: Aumentar el recvWindow (máximo 60000)
params["recvWindow"] = 10000
-1022 INVALID_SIGNATURE:
{"code": -1022, "msg": "Signature for this request is not valid."}
Causas comunes:
- El orden de los parámetros en la cadena de firma no coincide con el de la solicitud.
- Se agregaron comillas a parámetros numéricos.
- La Secret Key está truncada o contiene espacios.
- Diferencias en el método de codificación URL.
III. Errores de parámetros (-1100 a -1199)
| Código | Mensaje | Significado | Manejo |
|---|---|---|---|
| -1100 | ILLEGAL_CHARS | Caracteres ilegales | Limpiar la entrada |
| -1101 | TOO_MANY_PARAMETERS | Demasiados parámetros | Simplificar parámetros |
| -1102 | MANDATORY_PARAM_EMPTY_OR_MALFORMED | Parámetro obligatorio vacío o mal formado | Revisar documentación API |
| -1103 | UNKNOWN_PARAM | Parámetro desconocido | Eliminar campos adicionales |
| -1104 | UNREAD_PARAMETERS | Parámetros no leídos | Eliminar parámetros redundantes |
| -1105 | PARAM_EMPTY | Parámetro vacío | Introducir un valor válido |
| -1106 | PARAM_NOT_REQUIRED | Parámetro no requerido | Eliminarlo |
| -1111 | BAD_PRECISION | Precisión incorrecta | Ajustar a LOT_SIZE / PRICE_FILTER |
| -1112 | NO_DEPTH | Sin profundidad de mercado | Esperar a que el mercado se active |
| -1114 | TIF_NOT_REQUIRED | TIF no necesario | No enviar timeInForce en órdenes MARKET |
| -1115 | INVALID_TIF | TIF inválido | Usar GTC / IOC / FOK |
| -1116 | INVALID_ORDER_TYPE | Tipo de orden inválido | Revisar tipos admitidos |
| -1117 | INVALID_SIDE | Lado (side) inválido | Usar BUY o SELL |
| -1118 | EMPTY_NEW_CL_ORD_ID | ID de orden de cliente vacío | Proveer newClientOrderId o emitir |
| -1119 | EMPTY_ORG_CL_ORD_ID | ID de orden original vacío | Proveer orderId al cancelar/consultar |
| -1120 | BAD_INTERVAL | Intervalo de K-line inválido | Usar 1m/5m/15m/1h/4h/1d, etc. |
| -1121 | BAD_SYMBOL | Símbolo inválido | Validar con exchangeInfo |
| -1125 | INVALID_LISTEN_KEY | listenKey inválida | Llamar de nuevo a userDataStream |
| -1127 | MORE_THAN_XX_HOURS | Rango de tiempo excedido | Usar múltiples consultas |
| -1128 | OPTIONAL_PARAMS_BAD_COMBO | Mala combinación de parámetros | Revisar exclusiones en documentos |
| -1130 | INVALID_PARAMETER | Valor de parámetro ilegal | Corregir el rango del valor |
| -1131 | INVALID_JSON | Formato JSON incorrecto | Validar el JSON |
Detalles clave
-1111 BAD_PRECISION (Error de altísima frecuencia):
Filter failure: LOT_SIZE
Causa: La cantidad o el precio no cumplen con el stepSize / tickSize del par comercial.
# Práctica correcta: Consultar reglas de trading y redondear
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
# Normalizar antes de colocar la orden
quantity = round_step(0.0015789, step_size) # → 0.00157
price = round_step(60123.4567, tick_size) # → 60123.45
IV. Fallos de filtros (-1013)
-1013 INVALID_MESSAGE acompañado de diferentes filtros indica la causa específica:
| Tipo de filtro | Significado | Manejo |
|---|---|---|
| PRICE_FILTER | El precio no cumple tickSize | Redondear según tickSize |
| LOT_SIZE | La cantidad no cumple stepSize | Redondear según stepSize |
| MIN_NOTIONAL | Valor total demasiado bajo (<5 USDT) | Aumentar la cantidad |
| NOTIONAL | Valor nocional incorrecto | Igual que MIN_NOTIONAL |
| PERCENT_PRICE | Desviación de precio excesiva | Acercar al precio de mercado |
| MARKET_LOT_SIZE | Cantidad de orden market incorrecta | Cumplir reglas de orden market |
| MAX_NUM_ORDERS | Límite de órdenes abiertas excedido | Cancelar órdenes antes de poner nuevas |
| MAX_NUM_ALGO_ORDERS | Límite de órdenes algorítmicas excedido | Cancelar algunos Stop Loss / Take Profit |
V. Errores de órdenes (-2010 a -2099)
| Código | Mensaje | Significado | Manejo |
|---|---|---|---|
| -2010 | NEW_ORDER_REJECTED | Orden rechazada | Ver msg específico |
| -2011 | CANCEL_REJECTED | Cancelación rechazada | La orden podría estar ya ejecutada |
| -2013 | NO_SUCH_ORDER | La orden no existe | Revisar orderId |
| -2014 | BAD_API_KEY_FMT | Formato de Key incorrecto | Revisar longitud de 64 bits |
| -2015 | REJECTED_MBX_KEY | Key / IP / Permisos erróneos | Revisar lista blanca y permisos |
| -2016 | NO_TRADING_WINDOW | Sin ventana de trading | Par comercial suspendido |
| -2018 | BALANCE_NOT_SUFFICIENT | Saldo insuficiente | Depositar o reducir cantidad |
| -2019 | MARGIN_NOT_SUFFICIENT | Margen insuficiente | Bajar apalancamiento o añadir margen |
| -2020 | UNABLE_TO_FILL | Incapaz de ejecutar | Ajustar precio de orden límite |
| -2021 | ORDER_WOULD_IMMEDIATELY_TRIGGER | Se activaría de inmediato | Ajustar precios SL/TP |
| -2022 | REDUCE_ONLY_REJECT | Solo-reducción rechazada | Revisar dirección de posición |
| -2023 | USER_IN_LIQUIDATION | Usuario en liquidación | Esperar a que finalice |
| -2024 | POSITION_NOT_SUFFICIENT | Posición insuficiente | No se puede cerrar tanto |
| -2025 | MAX_OPEN_ORDER_EXCEEDED | Límite de órdenes abiertas superado | Cancelar órdenes antiguas |
| -2026 | REDUCE_ONLY_ORDER_TYPE_NOT_SUPPORTED | Tipo no admite solo-reducción | Cambiar a Market o Limit |
| -2027 | MAX_LEVERAGE_RATIO | Apalancamiento excedido | Reducir apalancamiento |
| -2028 | MIN_LEVERAGE_RATIO | Apalancamiento muy bajo | Aumentar apalancamiento |
Detalles clave
-2010 NEW_ORDER_REJECTED (El más común):
El campo msg dará la razón específica:
"Account has insufficient balance for requested action"→ Saldo insuficiente."Order would immediately match and take"→ La orden límite se ejecutaría de inmediato (en modo LIMIT_MAKER)."Filter failure: LOT_SIZE"→ La cantidad no cumple con el incremento de paso."Filter failure: PERCENT_PRICE"→ El precio se desvía demasiado.
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": "Saldo insuficiente"}
if "Filter failure: LOT_SIZE" in e.message:
return {"error": "Error de precisión en cantidad, redondear por stepSize"}
raise
-2015 REJECTED_MBX_KEY:
Tres causas secundarias (inferidas del mensaje de error):
- Formato de API Key incorrecto: Revisar longitud de 64 bits.
- IP no está en lista blanca: Iniciar sesión en Binance para actualizarla.
- Permisos no habilitados: Por ejemplo, llamar a /fapi/ sin marcar "Enable Futures".
VI. Errores de control de riesgo
| Código | Mensaje | Significado | Manejo |
|---|---|---|---|
| -4001 | PRICE_LESS_THAN_ZERO | Precio negativo | Revisar parámetros |
| -4002 | PRICE_GREATER_THAN_MAX_PRICE | Precio supera el máximo | Bajar el precio |
| -4003 | QTY_LESS_THAN_ZERO | Cantidad negativa | Cambiar a positiva |
| -4004 | QTY_LESS_THAN_MIN_QTY | Cantidad bajo el mínimo | Consultar LOT_SIZE |
| -4005 | QTY_GREATER_THAN_MAX_QTY | Cantidad supera el máximo | Dividir la orden |
| -4006 | STOP_PRICE_LESS_THAN_ZERO | Precio de parada negativo | Corregir |
| -4164 | MIN_NOTIONAL | Valor nocional bajo 5 USDT | Aumentar cantidad |
| -5021 | FOK_ORDER_REJECT | Orden FOK rechazada | Liquidez insuficiente, cambiar a GTC |
| -5022 | GTX_ORDER_REJECT | Orden GTX (Post Only) rechazada | El precio de mercado cambió, ya no es orden Maker |
VII. Middleware unificado de manejo de errores (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"Límite de frecuencia, esperando {retry_after}s")
time.sleep(retry_after)
continue
if r.status_code == 418:
raise SystemExit("IP bloqueada, terminando programa")
data = handle_response(r)
return data
except BinanceAPIError as e:
if e.code == -1021:
print("Desviación de tiempo, resincronizando")
# Reintentar después de sincronizar el tiempo
continue
if e.code in (-1001, -1006, -1007):
wait = 2 ** attempt
print(f"Error temporal {e.code}, reintentando en {wait}s")
time.sleep(wait)
continue
# Lanzar errores de negocio no reintentables
raise
return None
VIII. Preguntas frecuentes (FAQ)
P1: ¿Qué hacer si el código -1021 aparece repetidamente?
R: Es un problema de reloj del sistema. En Linux, habilite chronyd:
sudo systemctl enable chronyd
sudo chronyc sources -v # Verificar fuentes de sincronización
En Windows, vaya a Panel de control → Fecha y hora → Hora de Internet → Sincronizar con time.windows.com.
P2: ¿A qué se debe el error -1015 TOO_MANY_ORDERS?
R: El número de órdenes abiertas en un solo par comercial supera las 200 (Spot) o el límite establecido por el filtro MAX_NUM_ORDERS. Simplemente cancele algunas órdenes lejanas al precio.
P3: El error -2015 persiste después de revisar permisos e IP, ¿qué ocurre?
R: Verifique si está usando una Key de Spot en un dominio de Futures (fapi.binance.com) o viceversa. Los permisos para Spot y Futures son distintos; si una clave no tiene marcado "Enable Futures", no funcionará para interfaces de contratos.
P4: ¿Cómo registrar todos los códigos de error en los logs?
R: Encapsule una capa de middleware para contar por código de error:
from collections import Counter
error_counter = Counter()
def log_error(code: int):
error_counter[code] += 1
if error_counter[code] > 100:
alert(f"El error {code} ocurrió {error_counter[code]} veces, posible problema del sistema")
P5: ¿Cuál es la diferencia entre -1013 y -2010?
R: -1013 es un error de filtro (los parámetros no cumplen las reglas de trading), mientras que -2010 es una orden rechazada (rechazo en la capa de negocio, la razón está en el msg). El -1013 se puede evitar calculando previamente en el cliente, el -2010 depende más del estado del mercado en tiempo real (saldo, deslizamiento, control de riesgo).
Tras revisar la lista de códigos de error, regrese a la Navegación de categorías para consultar otros temas técnicos en la sección «Integración API».