12k
All articles

Explicación de Error.isError() en JavaScript

Error.isError() verifica errores reales de JavaScript entre realms, explica por qué supera a instanceof Error y muestra un fallback seguro.

OpenReplay Team
OpenReplay Team
Explicación de Error.isError() en JavaScript

Error.isError(value) es un método estático que devuelve true únicamente cuando value es un objeto Error genuino, y se mantiene fiable incluso entre realms porque comprueba una marca interna ([[ErrorData]]) en lugar de recorrer la cadena de prototipos.

Si alguna vez has abierto tu sistema de seguimiento de errores y te has encontrado con un {} vacío donde debería haber una excepción real, ya conoces el problema que esto resuelve. En algún punto del camino, una comprobación con instanceof decidió silenciosamente que tu error no era un error. Se estandarizó en ECMAScript 2026, lo que significa que las carencias históricas de instanceof Error (errores procedentes de iframes que se leen como no-errores, y objetos falsos que se leen como errores) tienen ahora una solución de primer nivel. Este artículo explica qué hace el método, por qué supera a instanceof, el mecanismo exacto que hay detrás, sus casos límite y cómo adoptarlo con un fallback seguro.

El comportamiento es exactamente el que cabría esperar: Error.isError(new Error()) es true, y Error.isError({ message: 'x' }) es false, porque el método verifica cómo se construyó el objeto, y no simplemente de qué hereda.

Puntos clave

  • Error.isError() realiza una comprobación de marca (branded check) sobre la ranura interna [[ErrorData]], la misma categoría de comprobación infalsificable que usa Array.isArray(), de modo que el código de usuario no puede burlarla.
  • instanceof Error falla de dos maneras opuestas: false para un error real creado en otro realm, y true para un objeto falso cuyo prototipo se fijó a Error.prototype.
  • El método devuelve true para subclases integradas como TypeError, para clases que extienden correctamente Error mediante extend Error, y para DOMException en los navegadores, aunque Safari actualmente devuelve false para DOMException.
  • Error.isError() forma parte de ECMAScript 2026 y está disponible en Chrome/Edge 134+, Firefox 138+, Node.js 24.0.0+ y Safari 18.4 (parcial).
  • Úsalo en los límites del sistema (manejadores globales, capas de logging, workers, iframes, SSR/edge), donde un fallo silencioso de instanceof convierte un error real en un objeto vacío en tus logs.

¿Por qué instanceof Error se queda corto?

instanceof Error falla de dos maneras opuestas, y ambas son silenciosas. La propuesta de TC39 detalla la primera: un error genuino que ha cruzado la frontera de un realm, ya sea desde un iframe o desde el módulo vm de Node, devuelve un falso negativo. Cada realm tiene su propio constructor Error, así que un error creado en un iframe no es una instancia de tu Error.

El segundo fallo es el inverso: cualquier objeto con Error.prototype en su cadena pasa la comprobación sin ser un error real. Aquí tienes cada fallo en código:

// Failure 1 — cross-realm error reads as NOT an error
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const crossRealmError = new iframe.contentWindow.Error('from iframe');

crossRealmError instanceof Error;   // → false  (wrong)
Error.isError(crossRealmError);     // → true   (correct)

// Failure 2 — fake object reads as an error
const fake = { message: "I'm not real" };
Object.setPrototypeOf(fake, Error.prototype);

fake instanceof Error;              // → true   (wrong)
Error.isError(fake);                // → false  (correct)

Ambos resultados corresponden al contrato documentado, no a un accidente. La referencia de MDN sobre el método lo presenta como la alternativa robusta a instanceof Error precisamente porque evita ambos modos de fallo: un prototipo prestado no basta para pasar la comprobación, y un error construido en otro realm sigue superándola. instanceof compara la identidad del constructor a lo largo de la cadena de prototipos, por lo que se equivoca en los dos casos.

Entradainstanceof Errorduck-typing ('message' in x)Error.isError()
Error de otro realm (iframe/worker/vm)false⚠️ dependetrue
Object.setPrototypeOf(obj, Error.prototype)true⚠️ truefalse
Instancia de class MyError extends Errortruetruetrue

¿Cómo funciona Error.isError() internamente?

Internamente, Error.isError() realiza una comprobación de marca sobre una ranura interna en lugar de inspeccionar la cadena de prototipos. MDN describe el mecanismo directamente: el método busca un campo privado que el constructor Error() instala en cada error que construye. Es el mismo truco que hay detrás de Array.isArray(), y un pariente cercano de la forma en que el operador in comprueba una propiedad.

Esa analogía con Array.isArray() es el modelo mental que conviene retener. Array.isArray() también acepta arrays construidos en un realm distinto, donde instanceof Array devuelve false porque cada realm mantiene un constructor Array independiente. Error.isError() lleva ese mismo marcado seguro entre realms a los errores.

El texto de la especificación en Stage 4 nombra la ranura como [[ErrorData]] y reduce la operación IsError a tres pasos: cualquier cosa que no sea un objeto falla de inmediato, cualquier cosa que lleve la ranura pasa, y todo lo demás falla. La ranura se establece en el momento de la construcción y no puede falsificarse desde JavaScript.

¿Por qué una ranura en lugar de Object.prototype.toString? Porque la suplantación de etiquetas rompió el truco antiguo. El autor de la propuesta llevó el problema al comité: en cuanto existió Symbol.toStringTag, una comprobación que había sido fiable e imposible de falsificar dejó de ser ambas cosas. Y dado que nada fuera de Object#toString consultaba jamás la ranura del error, el código de usuario se quedó sin ninguna prueba fiable. Error.isError() cubre exactamente ese hueco.

Detalles de comportamiento que conviene conocer

Error.isError() devuelve true para toda la familia de errores y false para todo lo demás, sin lanzar excepciones. Los ejemplos de MDN muestran que new Error(), new TypeError() y new DOMException() devuelven todos true, mientras que una llamada sin argumentos, o una que pase {}, null, undefined, 17 o la cadena "Error", devuelve false. Como el predicado de la especificación devuelve false para cualquier valor no-objeto y para los objetos que carecen de la ranura, los primitivos y null se gestionan limpiamente en lugar de provocar un error.

Las clases personalizadas correctamente extendidas sí se detectan, ya que heredan la marca:

class ValidationError extends Error {}
Error.isError(new ValidationError('bad input')); // → true

Solo se rechazan los imitadores que nunca llaman al constructor Error. El caso de DOMException tiene un matiz que conviene memorizar. La regla de MDN es que las instancias de DOMException pasan la comprobación. DOMException no es formalmente una subclase de Error, porque su constructor no hereda del constructor Error, pero lleva la misma marca, de modo que las comprobaciones de marca lo tratan igualmente como un error. Safari es la excepción: el resumen de Chrome del mes en que se lanzó Firefox 138 registra que Safari responde false para DOMException, razón por la cual el método no ha alcanzado el estado Baseline aunque todos los motores principales lo implementen ya. MDN sigue etiquetándolo como de disponibilidad limitada por el mismo motivo. Considera ese caso concreto como aún no uniforme.

Cuándo usar Error.isError()

Usa Error.isError() en los límites del sistema (manejadores globales de errores, capas de logging y de reporte de errores, test runners, librerías, SSR/edge, workers, iframes y extensiones de navegador), donde un fallo silencioso de instanceof convierte un error real en un {} vacío en tus logs. El instanceof simple está bien en código acotado y dentro del mismo realm; el beneficio está específicamente en los bordes, donde los valores cruzan contextos de ejecución.

Esto se corresponde con un modo de fallo real en el reporte: una comprobación con instanceof en un límite reclasifica un error genuinamente lanzado como un objeto plano, de modo que llega a tu pipeline sin mensaje ni stack. La repetición de sesiones (session replay) es una técnica útil en este punto: reproducir la sesión saca a la luz el error de consola que realmente se lanzó, evidenciando la brecha entre lo que vio el navegador y lo que reportó tu código intermedio. La solución es realizar la comprobación de marca con Error.isError() en esos límites antes de que nada se serialice o se registre.

Soporte en navegadores y runtimes, y un fallback seguro

Error.isError() forma parte de ECMAScript 2026, la 17.ª edición, que Ecma International ratificó el 30 de junio de 2026; la propuesta alcanzó el Stage 4 en la reunión de TC39 de mayo de 2025. En navegadores funciona a partir de Chrome y Edge 134, Safari 18.4 y Firefox 138, lanzado el 29 de abril de 2025. En el servidor, Node.js 24.0.0 lo incorporó gracias a la actualización a V8 13.6, que lo trajo junto con Float16Array, la gestión explícita de recursos, RegExp.escape y WebAssembly Memory64.

Para una mejora directa que degrade con elegancia en objetivos más antiguos, usa detección de características:

function isError(value) {
  return typeof Error.isError === 'function'
    ? Error.isError(value)      // realm-safe on modern engines
    : value instanceof Error;   // fallback, not realm-safe
}

En TypeScript, Error.isError(e) actúa además como type guard, estrechando un valor capturado de tipo unknown a Error dentro de la rama if, de modo que e.message es seguro a nivel de tipos sin necesidad de un cast manual.

Conclusión

Error.isError() cierra una brecha que ni el duck-typing ni instanceof pudieron cubrir: pregunta si el motor marcó realmente un valor como error, de modo que tanto los errores entre realms como las falsificaciones por suplantación de prototipo se resuelven correctamente. Migra hoy mismo tus comprobaciones en los límites (la capa de logging, los manejadores globales, las costuras de workers e iframes) al wrapper con detección de características, y reserva instanceof únicamente para el código que nunca sale de su propio realm.

Preguntas frecuentes

¿Error.isError() está estandarizado o sigue siendo una propuesta experimental?

Error.isError() está totalmente estandarizado. Avanzó al Stage 4 del proceso de TC39 en la 108.ª reunión de mayo de 2025 y está incluido en ECMAScript 2026, la 17.ª edición de la especificación del lenguaje. Ya no es una propuesta ni una característica experimental, así que las descripciones que lo califican de 'aún no estandarizado' o 'Stage 3' están desactualizadas. Trátalo como una característica del lenguaje ya disponible.

¿Error.isError() funciona con clases de error personalizadas?

Sí, siempre que la clase extienda correctamente Error. Una clase definida como 'class MyError extends Error {}' hereda la marca interna que establece el constructor Error, por lo que Error.isError(new MyError()) devuelve true. Solo se rechazan los objetos imitadores que nunca llaman al constructor Error, como un objeto plano al que se le ha forzado Error.prototype en su cadena. El requisito es la correcta creación de subclases, no el nombre de la clase.

¿Error.isError() funciona en Safari?

Safari 18.4 y versiones posteriores soportan Error.isError() para objetos Error normales, pero el soporte es parcial. Safari actualmente devuelve false para las instancias de DOMException, mientras que la especificación y los demás motores devuelven true. Debido a esta discrepancia, MDN no clasifica el método como Baseline, y web.dev lo señala como aún no disponible de forma uniforme. Gestiona el caso de DOMException de manera defensiva si tu código tiene a Safari como objetivo.

¿Es Error.isError() más rápido que instanceof Error?

Ambas son comprobaciones de tiempo constante en la práctica, así que el rendimiento no es la razón para cambiar. instanceof recorre la cadena de prototipos mientras que Error.isError() lee una única marca interna, pero la diferencia práctica es insignificante. La verdadera ventaja es la corrección: Error.isError() devuelve la respuesta correcta para errores entre realms y para falsificaciones por suplantación de prototipo, casos en los que instanceof falla silenciosamente. Elígelo por fiabilidad en los límites entre contextos de ejecución, no por velocidad.

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.