Desconexión de WebSocket de Tradovate por código de cierre 1006
Su WebSocket de Tradovate se cae con el código de cierre 1006 y sin ningún texto de motivo. Esto es lo que realmente significa el 1006, por qué se produce y cómo hacer que las reconexiones dejen de ser un problema.
Su WebSocket de Tradovate está alimentando felizmente a un bot y, de repente, se cae con el código de cierre 1006. Sin texto de motivo, sin mensaje de cierre, nada en los registros salvo alguna variante de “conexión cerrada de forma anómala.” Es uno de los fallos más frustrantes en la automatización de Tradovate precisamente porque el 1006 casi no le dice nada. La buena noticia: rara vez necesita resolver el misterio. Un 1006 significa que la conexión murió sin un cierre de protocolo limpio, y la solución fiable es hacer que su cliente se reconecte y se reautorice automáticamente en el instante en que ocurre: mantener los heartbeats activos, detectar la caída, levantar un socket nuevo, volver a iniciar sesión y volver a suscribirse. Un puente como PickMyTrade hace exactamente eso por debajo, de modo que sus alertas de TradingView sigan llegando a Tradovate incluso cuando un script sin más se habría quedado a oscuras.
Lista rápida de verificación para el código de cierre 1006
- Trate el 1006 como un síntoma. Significa que el socket se cayó sin un frame de cierre, no que un elemento específico esté roto.
- Envíe heartbeats. Envíe un frame vacío
[]aproximadamente cada 2.5 segundos. Si los omite, el servidor lo desconecta. - Reconéctese automáticamente ante cualquier cierre. No haga distinciones según el código. Reconéctese tanto ante un
1000limpio como ante un1006. - Reautorice y vuelva a suscribirse. Un socket nuevo no está autenticado, y las suscripciones de cotizaciones y de sincronización de usuario no sobreviven a una reconexión.
- Renueve, no vuelva a iniciar sesión. Renovar el token mantiene el socket activo; un inicio de sesión completamente nuevo puede expulsar su sesión y provocar la caída.
- Aplique backoff con jitter. Espacie los reintentos y limítelos para no superar los límites de solicitudes de Tradovate.
Qué significa el “código de cierre 1006”
Los códigos de cierre de WebSocket están definidos por el propio protocolo. Un cierre limpio envía el código 1000 (cierre normal) junto con un frame de cierre que explica el motivo. El código 1006 es distinto: es un código reservado que su librería de WebSocket asigna cuando la conexión desaparece sin que llegue nunca un frame de cierre. En otras palabras, la tubería TCP que hay debajo del socket se rompió, y ninguno de los dos lados tuvo la oportunidad de despedirse correctamente. Por eso el 1006 nunca lleva un motivo legible para humanos. No hay nada que leer, porque el mensaje que lo habría llevado nunca llegó a cruzar.
Ayuda saber cómo se comunica normalmente el socket de Tradovate. Cada frame que envía el servidor lleva marcado un único carácter inicial: un frame o es el mensaje de apertura que recibe en el momento en que el socket se conecta y es su señal para autenticarse; un frame a transporta un array de datos JSON (cotizaciones, actualizaciones de órdenes, respuestas de sincronización); un frame h es un heartbeat; y un frame c es un cierre ordenado. Cuando Tradovate cierra a propósito, envía c[1000,“...”] con un mensaje que explica el motivo. Un 1006 es lo opuesto a ese c ordenado: no hay ningún frame de cierre, solo un socket muerto y el código de cierre anómalo de la librería.
Así que deje de buscar un mensaje que nunca llegará, y pregúntese en cambio qué pudo haber cortado la conexión TCP bajo un socket de larga duración. Esa lista corta es donde vive toda solución real.
Principales causas del código de cierre 1006 en 2026
1. Heartbeats omitidos (la regla de los 2.5 segundos)
Esta es la causa que más se pasa por alto. Una vez que su frame authorize es aceptado, el socket de Tradovate espera un heartbeat constante de su cliente: un array JSON vacío, escrito literalmente como [], enviado aproximadamente cada 2.5 segundos. Esos pequeños frames demuestran que la conexión sigue viva. Si se detienen, el servidor puede dejar de enviar datos silenciosamente o cortar la conexión, lo que en su lado aparece como un 1006. Si sus desconexiones se agrupan tras una pausa en su código o un bucle de eventos saturado, sospeche primero del heartbeat.
2. Limitación de pestañas del navegador
Si su socket se ejecuta en un navegador, hay una trampa desagradable. Cuando la pestaña que aloja su aplicación no es la pestaña activa, Chrome y otros navegadores reducen la prioridad de setInterval y setTimeout. Su heartbeat de 2.5 segundos se retrasa hasta cada varios segundos, el servidor detecta una conexión estancada, y el socket se cierra con 1006 en el momento en que cambia de pestaña. La solución es ejecutar el bucle del heartbeat en un web worker (los workers no se ven limitados de la misma forma) o ejecutar todo el proceso como un proceso de Node completamente fuera del navegador.

3. Tiempos de espera agotados en proxy, NAT o firewall inactivos
Cualquier elemento situado entre su máquina y Tradovate puede cortar una conexión que cree que se ha quedado en silencio. Los proxies corporativos, los balanceadores de carga, las tablas NAT y los routers domésticos suelen cortar las conexiones TCP inactivas después de 30 a 120 segundos, y rara vez envían un frame de cierre cuando lo hacen. Eso es un 1006 de manual, y un heartbeat con el ritmo adecuado es lo que mantiene el enlace con actividad suficiente para sobrevivir.
4. Expiración del token o una segunda sesión que le roba la sesión
Un token de acceso de Tradovate vive alrededor de 90 minutos, y dejar que expire mientras el socket está conectado puede cortar la conexión. Peor aún, Tradovate solo permite dos sesiones simultáneas por cuenta, y crear una tercera cierra la más antigua. Si otro script, una prueba manual o un nuevo flujo de inicio de sesión solicita un token nuevo para la misma cuenta, puede expulsar la sesión sobre la que va montado su socket, lo que de nuevo aparece como un 1006. El patrón seguro es renovar el token con un temporizador en lugar de volver a iniciar sesión, lo que mantiene viva la sesión existente, y el socket.
5. Inestabilidad de red y tormentas de reconexión
Las simples caídas de red también provocan 1006: un enlace Wi-Fi inestable, un VPS con un vecino ruidoso, un pequeño fallo del proveedor de internet. Eso es hasta cierto punto inevitable. La trampa está en cómo responde. Si su lógica de reconexión se dispara en un bucle apretado en cuanto detecta un cierre, puede saturar el endpoint de Tradovate con intentos de conexión, activar su penalización de solicitudes y convertir un fallo de dos segundos en un bloqueo de varios minutos. Aquí el backoff no es opcional.
Cómo solucionar el código de cierre 1006: paso a paso
Envuelva el socket y reconéctese ante cualquier cierre
Controle todo el ciclo de vida
Coloque su WebSocket dentro de una clase o función que controle todo el ciclo de vida: conexión, autorización, suscripción, heartbeat y cierre.
Adjunte un único manejador de cierre
Adjunte un único manejador de cierre que se dispare ante cualquier cierre, limpio o anómalo. No haga distinciones según el código. Tanto un 1000 como un 1006 significan “el socket ha desaparecido, reconstrúyalo.”
Limpie el socket muerto y programe una reconexión
Al cerrarse, elimine todas las referencias al socket muerto, cancele su temporizador de heartbeat y programe una reconexión. Nunca reutilice un objeto de socket cerrado.
Guarde su estado antes de que se desmonte
Antes de desmontarlo, guarde el estado que necesitará restaurar: a qué contratos estaba suscrito, si había una solicitud de sincronización de usuario abierta, y su token actual.
Mantenga el heartbeat activo
Inicie el heartbeat una vez autorizado
En cuanto se acepte su frame authorize, comience a enviar un frame vacío [] cada 2.5 segundos.
Traslade los temporizadores del navegador a un web worker
Si está en un navegador, traslade ese temporizador a un web worker para que una pestaña en segundo plano no pueda limitarlo. En Node, un simple intervalo es suficiente.
Vigile también el otro extremo
Vigile también el otro extremo. Si pasan más de unos segundos sin recibir ningún frame del servidor, trate la conexión como muerta y fuerce una reconexión en lugar de esperar.

Reautorice y vuelva a suscribir el nuevo socket
Espere el frame de apertura
Espere el frame de apertura o en el socket nuevo. Solo entonces estará listo para autenticarse.
Envíe de nuevo el frame authorize
Envíe de nuevo el frame authorize con un token de acceso válido, con el formato exacto que especifica la documentación actual de la API (la palabra clave de la solicitud, un id, luego el token, con los separadores de línea en blanco correctos).
Repita todas las suscripciones
Una vez que la autorización se realiza con éxito, repita todas las suscripciones a partir de su estado guardado: suscripciones de cotizaciones, solicitudes de sincronización de usuario y cualquier otra cosa que llevara el socket anterior.
Concilie después de la interrupción
Concilie después de la interrupción. Obtenga las posiciones actuales y las órdenes activas para que su vista coincida con la realidad, ya que pueden haberse producido eventos mientras estaba desconectado.
Renueve el token con un temporizador, no genere una nueva sesión
Guarde la expiración y configure un temporizador de renovación
Cuando inicie sesión por primera vez, guarde la expiración del token y configure un temporizador para renovarlo aproximadamente 15 minutos antes de que caduque.
Renueve a través del endpoint de renovación
Renueve a través del endpoint de renovación, que extiende su sesión sin necesidad de un nuevo inicio de sesión. El socket conectado sigue funcionando sin que se requiera nada más.
Nunca genere un segundo inicio de sesión
Nunca inicie un inicio de sesión completamente nuevo para una cuenta que ya tiene un socket activo. Eso puede hacer que supere el límite de dos sesiones y provocar la caída del socket que está intentando proteger.

Aplique backoff con jitter
Comience con uno a dos segundos
En la primera reconexión, espere de uno a dos segundos. En cada fallo posterior, duplique aproximadamente el retraso.
Añada un pequeño desplazamiento aleatorio
Añada un pequeño desplazamiento aleatorio a cada retraso para que muchos clientes no reintenten todos en el mismo instante y saturen el endpoint a la vez.
Limite el máximo
Limite el máximo entre 30 y 60 segundos. Un backoff limitado y con jitter se recupera rápido de un fallo puntual sin convertirse en un bloqueo de límite de solicitudes autoinfligido.
Tabla de resolución de problemas
| Síntoma | Causa probable | Solución |
|---|---|---|
| 1006 a los pocos segundos de cambiar de pestaña del navegador | Temporizador de heartbeat limitado en una pestaña en segundo plano | Ejecute el heartbeat [] en un web worker o en Node |
| 1006 tras una pausa del código o un bucle saturado | Heartbeat detenido más allá de ~2.5 segundos | Envíe [] en un intervalo fiable de 2.5s, además de con los frames entrantes |
| 1006 tras 30 a 120 segundos de inactividad | El proxy, NAT o firewall cortó un enlace TCP inactivo | Mantenga los heartbeats activos para que el enlace nunca parezca inactivo |
| 1006 justo alrededor de la marca de los 90 minutos | El token de acceso expiró | Renueve el token ~15 minutos antes de que caduque |
| 1006 en el momento en que inicia sesión en otro lugar | Una nueva sesión le hizo superar el límite de 2 sesiones | Renueve en lugar de volver a iniciar sesión; una sesión por cuenta |
| Tormentas de 1006, seguidas de un bloqueo prolongado | Un bucle de reconexión apretado activó la penalización de solicitudes | Backoff exponencial con jitter, limitado a 30-60s |
Evite esto con PickMyTrade
Una capa de reconexión, un heartbeat resistente a la limitación, un renovador de tokens y una repetición de suscripciones son mucha fontanería que hay que acertar a mano, y un solo caso extremo pasado por alto tira sus órdenes en el peor momento. PickMyTrade se sitúa entre TradingView y Tradovate y se encarga de todo esto por usted:
- Conexiones WebSocket gestionadas con reconexión y reautorización automáticas, de modo que un 1006 se convierte en un simple parpadeo en lugar de una interrupción.
- Heartbeats siempre activos que se ejecutan del lado del servidor, muy lejos de la limitación de pestañas del navegador.
- Renovación automática de tokens y una única sesión limpia por cuenta, de modo que una expiración a los 90 minutos o un segundo inicio de sesión accidental nunca lo dejen fuera de línea.
- Reconexiones seguras frente a los límites de solicitudes con un backoff sensato, de modo que la recuperación nunca se convierta en un bloqueo por penalización de solicitudes.
El resultado: sus alertas de TradingView llegan a Tradovate de forma fiable sin que usted tenga que escribir ni supervisar una sola línea de código del ciclo de vida del WebSocket.
Nunca deje que un 1006 lo deje fuera de línea
PickMyTrade gestiona por usted la reconexión, la reautorización y la lógica de heartbeat, de modo que un WebSocket de Tradovate caído le cuesta un segundo, no una sesión.
Comience su prueba gratuita de 5 díasPreguntas frecuentes
El código 1006 es un cierre anómalo. La conexión TCP subyacente se cayó sin que ninguno de los dos lados enviara un frame de cierre de WebSocket adecuado, por lo que su librería informa 1006 sin texto de motivo. Es un síntoma, no una causa raíz: algo por debajo de la capa de WebSocket (un tiempo de espera agotado, un reset, un heartbeat omitido o una red caída) mató la tubería antes de que pudiera producirse un cierre 1000 limpio.
Los desencadenantes habituales son los heartbeats omitidos (Tradovate espera un frame de array vacío aproximadamente cada 2.5 segundos), un proxy o firewall inactivo que agota el tiempo de espera de la conexión TCP, el token de acceso que expira o queda invalidado por un segundo inicio de sesión, o simplemente inestabilidad de red en un VPS o una conexión doméstica. Como el 1006 oculta el motivo exacto, la solución práctica es reconectarse y reautorizarse automáticamente en lugar de perseguir una única causa.
Aproximadamente cada 2.5 segundos. Una vez que se acepta su frame authorize, el cliente debe enviar un frame de array JSON vacío escrito como [] en ese intervalo. Si esos heartbeats se detienen, el servidor puede dejar de enviar datos o cerrar la conexión directamente, lo que a menudo aparece en su lado como un 1006.
Sí. Un socket completamente nuevo comienza sin autenticar. Una vez que se abre, tiene que volver a enviar el frame authorize con un token de acceso válido y, después, reenviar todas las suscripciones (cotizaciones, sincronización de usuario, etc.). Las suscripciones y la autorización no se conservan del socket que acaba de morir.
Renovar no lo hace. Llamar al endpoint de renovación mantiene válida su sesión existente, y el socket ya conectado se mantiene activo sin necesidad de hacer nada más. Lo que sí lo corta es solicitar un token completamente nuevo con un nuevo inicio de sesión: Tradovate solo permite dos sesiones simultáneas, por lo que una nueva sesión puede expulsar la más antigua sobre la que va montado su socket, y usted ve un 1006.
Chrome y otros navegadores limitan setInterval y setTimeout en las pestañas inactivas para ahorrar energía. Esa limitación retrasa su heartbeat de 2.5 segundos, el servidor detecta una conexión estancada, y el socket se cierra con 1006. Ejecutar el heartbeat en un web worker o en un proceso de Node, en lugar de en una pestaña en segundo plano, evita esa limitación.
Utilice un backoff exponencial con un poco de jitter aleatorio. Comience alrededor de uno a dos segundos, duplique aproximadamente el retraso en cada intento fallido, añada un pequeño desplazamiento aleatorio para que muchos clientes no reintenten al mismo ritmo, y limite el máximo a entre 30 y 60 segundos. Reconectarse en un bucle apretado puede activar la penalización de solicitudes de Tradovate y hacer que la interrupción dure más.
Ninguna conexión es inmune al 1006, porque las redes, los proxies y los servidores ocasionalmente cortan los sockets de larga duración. El objetivo no es eliminarlo, sino convertirlo en algo intrascendente: mantener los heartbeats activos, detectar el cierre al instante, reconectarse y reautorizarse con un backoff, y volver a suscribirse. Hecho correctamente, un 1006 le cuesta uno o dos segundos en lugar de dejar su bot fuera de línea.
Esta guía tiene fines educativos e informativos únicamente y no constituye asesoramiento financiero, de inversión ni de trading. Operar con futuros y otros productos apalancados conlleva un riesgo sustancial de pérdida y no es adecuado para todos los inversores. PickMyTrade es una plataforma de automatización independiente de terceros y no está afiliada, respaldada ni patrocinada por Tradovate, Inc. ni por Bookmap. Todos los nombres, logotipos y marcas relacionados son propiedad de sus respectivos dueños. Las funciones y los pasos de la plataforma cambian con el tiempo, así que confirme siempre el proceso vigente en la documentación oficial de la plataforma antes de actuar.