Módulo 2: Fundamentos del inglés técnico: leer y escuchar

4. El inglés de los errores, logs y stack traces

Descripción

Hay un inglés que ya lees cientos de veces por semana aunque no te des cuenta: el de los mensajes de error. Cuando algo se rompe, la terminal te habla en inglés, y ese inglés no es prosa libre — es un dialecto pequeño, repetitivo y con reglas fijas. Las mismas veinte fórmulas aparecen en Python, en JavaScript, en Rust, en un log de servidor y en una respuesta de una API. Dominar ese dialecto es probablemente la mejor relación esfuerzo/recompensa de toda esta guía: es poco vocabulario, se repite muchísimo, y cada palabra que reconoces te ahorra minutos de depuración a ciegas.

Este módulo trata de consumir inglés antes de producirlo, y aquí llegamos al inglés más denso de todos: el de la máquina cuando falla. La lección anterior te dio el método para leer documentación sin traducir; esta te da el método para leer lo que la documentación no cubre — el momento en que tu código está roto y el único que te explica por qué es un mensaje en inglés que la mayoría de la gente ignora, copia y pega en un buscador sin siquiera leerlo. Vamos a leerlo. Porque casi siempre el error ya te dijo qué hacer, solo que en un idioma que aprendiste a saltarte.

Un aviso honesto sobre el nivel: esta guía asume que ya lees inglés técnico con cierta soltura (nivel B1 de lectura) y que puedes sostener un par de minutos hablando con errores. Si al abrir un stack trace tu instinto es cerrarlo y buscar la traducción, este módulo es exactamente para ti — no porque no sepas inglés, sino porque nadie te enseñó que los errores tienen gramática propia. Y si sientes que "no sabes suficiente inglés para programar en serio", quédate: al terminar esta lección vas a reconocer que el 90% de lo que la máquina te grita son las mismas frases hechas.

Conexión con el módulo: Este es el cuarto escalón de "leer y escuchar". El vocabulario nuclear (lección 2) y la lectura de documentación (lección 3) te prepararon para el texto que la industria escribe con calma. Los errores son lo contrario: texto que la máquina escupe bajo presión, sin párrafos, sin ejemplos amables. Es el insumo que después vas a citar en un issue (lección 5), reportar en un standup y pegar en un PR. Leer bien un error hoy es escribir bien un reporte mañana.


Por qué los errores hablan siempre igual

Un mensaje de error no lo escribió un poeta. Lo escribió un desarrollador, dentro de una librería, en el momento de programar la condición que falla. Y como escribir mensajes de error es tedioso, todo el mundo copia las mismas fórmulas. El resultado es una suerte para ti: el inglés de los errores es cerrado. Hay un puñado de plantillas que se repiten en todos los lenguajes y todas las herramientas.

Piénsalo como las señales de tránsito. No lees cada señal como una frase nueva: reconoces la forma del octágono rojo y ya sabes "alto" antes de leer la palabra. Los errores funcionan igual. Cuando entrenas el ojo, dejas de leer el mensaje letra por letra y reconoces el patrón completo de un vistazo.

Estas son las fórmulas que cubren la enorme mayoría de los casos. Apréndetelas como bloques, no como palabras sueltas:

Fórmula en inglésQué está diciendoQué esperar / qué hacer
expected X, got YEsperaba X, recibió YUn desajuste de tipo o forma. Compara lo que mandaste contra lo que pedía
cannot <verbo> / unable to <verbo>No puede / no logra hacer algoLa operación no se pudo completar. Lee el verbo: cannot read, cannot find, cannot connect
X is not defined / X is undefinedX no existe / no tiene valorUsaste algo que no declaraste o que llegó vacío. Típico error de nombre o de import
X is not a functionX no es una funciónEstás llamando X() pero X es otra cosa (un objeto, undefined)
must be <algo>Debe ser (tal cosa)Una regla de validación. Te dice el requisito exacto que incumpliste
<algo> refused(Algo) fue rechazadoCasi siempre red: connection refused. Nada está escuchando del otro lado
timed out / timeoutSe agotó el tiempoAlgo tardó más de lo permitido. Red lenta, servicio caído, o un límite muy corto
X not foundNo se encontró XUna ruta, un archivo, un módulo, un endpoint que no existe donde buscaste
permission deniedPermiso denegadoFalta un permiso: de archivo, de usuario, de sistema
already existsYa existeIntentaste crear algo que ya estaba. Común en archivos, puertos, registros de BD
out of range / index out of boundsFuera de rangoPediste la posición 10 de una lista de 3. Error clásico de índice
unexpected <algo>(Algo) inesperadoEl parser encontró algo donde no debía: unexpected token, unexpected end of input

Fíjate en el par estrella: expected X, got Y. Es la fórmula más útil de todo el dialecto porque te entrega el diagnóstico ya masticado. No dice "hay un problema"; dice exactamente qué esperaba y qué llegó en su lugar. Cuando veas esa estructura, tu trabajo es simple: encontrar por qué Y llegó donde debía ir X.

Un matiz de vocabulario que confunde a muchos: cannot y unable to significan lo mismo (no se puede), pero cannot suele describir una imposibilidad dura ("esto no se puede hacer nunca así") y unable to una falla del intento ("no logré hacerlo esta vez"). No te frenes en la diferencia — para depurar, ambos significan "esta operación no ocurrió, lee el verbo que sigue".

Anatomía de un stack trace: qué línea leer primero

Un stack trace (traza de pila) es la fotografía que toma el programa en el instante exacto en que se rompió. La palabra stack es literal: es una pila de llamadas. Tu función main llamó a process, que llamó a parse, que llamó a read, y fue en read donde todo explotó. El stack trace te muestra ese camino completo, de adentro hacia afuera o de afuera hacia adentro según el lenguaje.

Aquí está la mala noticia y la buena. La mala: un stack trace puede tener treinta líneas y da miedo. La buena: casi nunca necesitas leer las treinta. Necesitas leer dos.

Veamos un ejemplo real de Python. Léelo sin traducir, solo buscando la forma:

Traceback (most recent call last):
  File "app.py", line 42, in <module>
    result = process_order(order)
  File "services/orders.py", line 17, in process_order
    total = calculate_total(order["items"])
  File "services/orders.py", line 8, in calculate_total
    return sum(item.price for item in items)
KeyError: 'items'

Cómo se lee esto, paso a paso:

  1. La primera línea es una etiqueta, no información. Traceback (most recent call last) significa literalmente "seguimiento (la llamada más reciente va al final)". Te está avisando el orden: en Python, lo que se rompió está abajo. Otros lenguajes lo ponen al revés. Aprende de cada herramienta dónde está el fondo.

  2. La última línea es el veredicto. KeyError: 'items' es el error. Todo lo de arriba es el camino que llevó hasta él. Si solo pudieras leer una línea, lee esta. Te dice el tipo (KeyError) y el detalle ('items'): buscaste la clave items en algo que no la tenía.

  3. La penúltima sección relevante es el lugar del crimen. File "services/orders.py", line 8, in calculate_total con return sum(item.price for item in items). Ahí, en la línea 8, es donde tu código tocó el problema. Ese es el punto de entrada de tu depuración.

Con esas dos líneas ya tienes una hipótesis completa: "En calculate_total, algo llamado items no existe como clave; el order que llegó no tiene la forma que esperaba mi código." No traduje nada. Reconocí el patrón.

La regla de oro del stack trace: lee de los extremos hacia el centro. El fondo te da qué falló (el tipo de error y su mensaje). El marco más profundo de tu código te da dónde. Las líneas del medio, casi siempre dentro de librerías que no escribiste, se leen solo si las dos puntas no bastaron.

Un detalle práctico que ahorra horas: distingue tu código del ajeno. Los frameworks meten decenas de marcos internos (node_modules, site-packages, vendor) que rara vez son la causa. Entrena el ojo para saltar hasta la primera línea que menciona un archivo tuyo. Ese suele ser el verdadero punto de partida.

Comparando el mismo trace entre lenguajes

El vocabulario de la pila viaja entre lenguajes con pequeñas variaciones. Reconocer estas palabras te vuelve políglota de errores:

Palabra en inglésSignificadoDónde la ves
TracebackLa traza completaPython
Stack traceLa traza completaJava, JS, C#, casi todos
at <función> (<archivo>:<línea>)Un marco de la pilaJavaScript / Node
Caused by:La causa raíz encadenadaJava, Kotlin
panic:Fallo no recuperableGo, Rust
thread 'main' panicked atEl hilo que reventóRust
most recent call lastLo roto está al finalPython
frameUn nivel de la pilaDepuradores en general

Presta atención especial a Caused by: (causado por). En el mundo Java/Kotlin, un error suele envolver a otro. Ves un RuntimeException arriba, pero tres Caused by: más abajo aparece el verdadero culpable: un NullPointerException en tu código. La técnica: baja hasta el último Caused by:. Ahí, casi siempre, está la raíz. Lo de arriba es solo el envoltorio con el que viajó.

El vocabulario de la severidad: niveles de log

Un log es el diario que un programa escribe mientras corre: una línea por cada cosa que le parece digna de anotar. Cada línea trae un nivel que dice qué tan grave es. Confundir los niveles es un error de novato que se nota; entenderlos te deja leer un log de producción sabiendo dónde mirar.

Estos son los cinco niveles estándar, del más ruidoso al más urgente. El texto en inglés es exactamente el que verás en cualquier sistema del mundo:

NivelSignificado literalQué tan preocupado estar
DEBUGDepuraciónDetalle fino para desarrollo. En producción normalmente está apagado
INFOInformación"Todo normal, esto pasó." Ruido de fondo saludable
WARNING / WARNAdvertencia"Algo raro, pero seguí funcionando." Vale la pena mirarlo
ERRORError"Algo falló y no pude completarlo." Esto sí duele
CRITICAL / FATALCrítico / Fatal"Me estoy cayendo entero." Máxima urgencia

Cuando abras un log gigante, no lo leas línea por línea. Filtra por severidad. Busca primero ERROR y FATAL; ignora el mar de INFO. Una técnica que usan los profesionales: leer de abajo hacia arriba (los logs más nuevos suelen estar al final) buscando el primer ERROR en orden cronológico. Muchas veces un solo fallo temprano desata una cascada de errores posteriores, y solo el primero importa.

Vocabulario de severidad que aparece dentro de los mensajes, más allá de la etiqueta del nivel:

  • deprecatedobsoleto, en vías de eliminación. No es un error todavía, es un aviso de que lo será. "This method is deprecated and will be removed in v4."
  • fatalfatal, sin retorno. El programa no puede seguir.
  • severegrave. Variante de alto nivel en algunos sistemas (Java Logger).
  • retryingreintentando. El sistema tropezó pero lo va a intentar de nuevo. Verlo repetido muchas veces suele indicar un problema de fondo.
  • stalerancio, viejo, desactualizado. Un dato o una conexión que ya no sirve. stale connection, stale cache.

Los mensajes que mienten (y cómo reconocerlos)

Aquí viene la parte que separa a quien lee errores de quien los sufre. No todos los mensajes de error apuntan a la causa real. Algunos son honestos; otros son síntomas que señalan al lugar equivocado. Reconocer los mentirosos crónicos te ahorra perseguir fantasmas.

Los sospechosos habituales:

Segmentation fault / segfault — En inglés significa "fallo de segmentación", pero como mensaje es casi inútil: te dice que el programa tocó memoria que no debía, no dónde ni por qué. Es el equivalente a que el carro haga "clonc" sin decir qué pieza. No busques la causa en las palabras; busca en el stack trace o corriendo con un depurador.

Cannot read property 'x' of undefined (JavaScript) — El mensaje señala la propiedad x, pero la culpa nunca es de x. La culpa es de que lo que está antes del punto llegó undefined. El error dice "no puedo leer x" cuando la verdad es "el objeto donde busco x no existe". Lee siempre hacia la izquierda del punto.

Module not found justo después de instalar algo — El mensaje dice que el módulo no existe, pero muchas veces sí existe: lo que falla es la ruta, la versión de Node/Python activa, o una caché vieja. El texto es literal pero la causa está un nivel más abajo de lo que dice.

Errores en cascada — Cuando ves quince errores idénticos seguidos, catorce mienten. Solo el primero cuenta; los demás son el eco de ese primero. Perseguir el último error de la lista es el error de depuración más común que existe.

NullPointerException sin más contexto (Java) — Te dice qué pasó (algo era null) pero el "qué era null" hay que deducirlo del número de línea, no del mensaje. El mensaje es honesto pero incompleto por naturaleza.

La lección de fondo: el mensaje de error es la primera hipótesis, no el veredicto final. Créele lo justo. Un buen lector de errores toma el texto, lo convierte en una teoría, y va a verificarla al código — no la da por cierta solo porque está en inglés y suena seguro.

De texto en inglés a acción concreta: el puente

Todo lo anterior converge en una sola habilidad: convertir un mensaje en inglés en la siguiente cosa que vas a hacer. Este es el puente, con tres pasos:

  1. Ubica el tipo y el detalle. El sustantivo del error (KeyError, TypeError, ConnectionRefusedError) es la categoría; el texto que sigue es el detalle. Léelos juntos.
  2. Traduce la fórmula a una hipótesis. Usa la tabla de fórmulas. expected str, got int no es "hay un error de tipos": es "en algún lado mandé un número donde el código quería texto".
  3. Convierte la hipótesis en acción. La hipótesis siempre apunta a un lugar del código. Ve ahí primero.

Veamos el puente en acción con errores reales que verás mil veces:

Mensaje en inglésHipótesis de causaAcción concreta
TypeError: expected str, got intPasé un número donde se esperaba textoEncuentra la variable y conviértela con str()
ConnectionRefusedError: [Errno 111]Nada escucha en esa dirección/puertoVerifica que el servicio/BD esté corriendo y el puerto correcto
ModuleNotFoundError: No module named 'requests'La librería no está instalada en este entornoInstálala, o revisa que el entorno virtual sea el correcto
PermissionError: [Errno 13] Permission deniedEl proceso no tiene permiso sobre ese recursoRevisa permisos del archivo, o si necesitas privilegios elevados
JSONDecodeError: Expecting value: line 1 column 1Intenté parsear como JSON algo que no lo esImprime la respuesta cruda: probablemente sea HTML de error o esté vacía
IndexError: list index out of rangePedí una posición que la lista no tieneRevisa el largo de la lista antes de indexar
TimeoutErrorLa operación no respondió a tiempoVerifica la red/servicio; considera si el límite es demasiado corto

Fíjate en JSONDecodeError: Expecting value: line 1 column 1. El mensaje parece hablar de sintaxis JSON, pero en la práctica casi siempre significa una cosa muy distinta: pediste datos a una API, algo salió mal, y te devolvió una página de error en HTML o una respuesta vacía en lugar de JSON. El error es técnicamente cierto ("esperaba un valor en la línea 1") pero la causa real está un paso antes. Ese salto — del texto literal a la causa real — es exactamente lo que entrenas al leer muchos errores.

Qué esperar cuando empieces a leer errores en serio

Un cierre honesto sobre la curva. Las primeras semanas vas a sentir que lees más lento, porque estás forzándote a leer el error en vez de saltar directo al buscador. Es incómodo y es correcto. Estás construyendo el reconocimiento de patrones que después va a ser instantáneo.

Lo que va a pasar, en orden:

  • Semana 1-2: Reconoces las fórmulas (expected/got, cannot, not found) sin traducir. Todavía dudas de los stack traces largos.
  • Semana 3-4: Vas directo a la última línea de un trace y al primer archivo tuyo. Los logs dejan de ser un muro; filtras por ERROR sin pensarlo.
  • Después: Un error en inglés deja de ser texto extranjero. Se vuelve una instrucción. Empiezas a predecir qué va a decir el error antes de leerlo completo.

Una nota sobre el síndrome del impostor lingüístico, porque este módulo lo toca de lleno. Si alguna vez pensaste "no puedo ser buen desarrollador porque mi inglés no alcanza", mira lo que acabas de hacer en esta lección: leíste stack traces en Python, reconociste Caused by: de Java, entendiste niveles de log y desarmaste cinco mensajes mentirosos. Eso es inglés técnico de trabajo. No necesitabas fluidez conversacional para nada de esto. El inglés de los errores es el más acotado y el más aprendible de todos los ingleses de nuestra profesión — y lo estás leyendo ya.

Un método de práctica que sí funciona

Leer sobre errores no basta; hay que masticarlos. Aquí tienes una cadencia concreta para las semanas de este módulo:

  • A diario (5 min): Cada vez que tu propio código falle, antes de copiar el error a un buscador, léelo en voz baja en inglés y formula tu hipótesis en una frase. Solo entonces busca. Estás usando tus propios errores como material de estudio gratis.
  • Cadencia semanal: Guarda en tu bitácora tres errores nuevos que hayas encontrado, con su fórmula, su hipótesis y qué resultó ser. En pocas semanas tendrás tu propio diccionario de errores reales, mucho más útil que cualquier lista genérica.
  • Escucha, no solo lectura: Busca un video de alguien depurando en inglés (hay decenas de streams de programación en vivo) y ponte a escuchar cómo narran un error. Vas a oír las mismas fórmulas dichas en voz alta: "so it says cannot read property of undefined, which means...". Oír el error después de leerlo cierra el círculo, y prepara el oído para el inglés hablado técnico que trabajaremos con método más adelante en el módulo.

La puerta que este método abre es simple: cuando los errores en inglés dejen de asustarte, la documentación deja de asustarte, los issues dejan de asustarte, y — más adelante en la guía — explicar un bug en voz alta en un standup deja de asustarte. Todo empieza aquí, en la línea que la máquina ya te escribió y que hoy vas a leer completa.

Ejercicios

Estos ejercicios ejercitan lo que enseñó la lección: leer las fórmulas, ubicar las dos líneas clave de un stack trace, filtrar un log por severidad y desconfiar de los mensajes que mienten. Haz cada uno antes de abrir la solución. El objetivo no es acertar de memoria, sino entrenar el ojo para reconocer el patrón sin traducir.

Ejercicio 1 — Las dos líneas que importan

Tienes este stack trace de Python. Sin traducir palabra por palabra, responde: (a) ¿cuál es la línea del veredicto y qué dice?, (b) ¿cuál es la primera línea de tu código donde tocó el problema?, (c) escribe tu hipótesis en una sola frase.

Traceback (most recent call last):
  File "main.py", line 30, in <module>
    send_invoice(user)
  File "billing/invoice.py", line 12, in send_invoice
    email = user["contact"]["email"]
TypeError: string indices must be integers
Ver solución

(a) El veredicto es la última línea: TypeError: string indices must be integers ("los índices de un string deben ser enteros"). El tipo es TypeError; el detalle dice que intentaste indexar un string con una clave de texto.

(b) La primera línea de tu código es File "billing/invoice.py", line 12, in send_invoice, con email = user["contact"]["email"]. Ahí, en la línea 12, está el lugar del crimen.

(c) Hipótesis: "user["contact"] no es el diccionario que esperaba mi código, sino un string; por eso ["email"] falla, porque a un string solo se lo indexa con números."

Por qué funciona: aplicaste la regla de oro (leer de los extremos hacia el centro): la última línea da qué falló y el primer marco de tu código da dónde. Las líneas del medio no hicieron falta.

Ejercicio 2 — De la fórmula a la acción

Empareja cada mensaje en inglés con su hipótesis de causa y la primera acción concreta que tomarías.

  1. ConnectionRefusedError: [Errno 111] Connection refused
  2. ValueError: could not convert string to float: 'N/A'
  3. FileNotFoundError: [Errno 2] No such file or directory: 'config.yaml'
Ver solución
  1. Causa: nada está escuchando en esa dirección o puerto (refused = rechazado, casi siempre red). Acción: verifica que el servicio o la base de datos esté corriendo y que el puerto sea el correcto.
  2. Causa: intentaste convertir a número un texto que no es un número ('N/A'). Es la fórmula could not <verbo> = unable to. Acción: limpia o filtra los valores no numéricos antes de convertir.
  3. Causa: la ruta config.yaml no existe donde el programa la buscó (not found). Acción: revisa el nombre y la ruta del archivo, y desde qué directorio se ejecuta el programa.

Por qué funciona: cada mensaje contiene una de las fórmulas fijas del dialecto (refused, could not convert, No such file). Reconocer el bloque te lleva directo a la hipótesis, y la hipótesis siempre apunta a un lugar concreto donde actuar.

Ejercicio 3 — El mensaje que miente

Un compañero te muestra este error de JavaScript y dice: "el problema está en la propiedad name, la voy a renombrar". ¿Tiene razón? Explica dónde está de verdad la causa.

TypeError: Cannot read property 'name' of undefined
    at renderProfile (profile.js:8)
Ver solución

No tiene razón. El mensaje señala name, pero la culpa nunca es de name: la culpa es de que lo que está antes del punto llegó undefined. El error real es "el objeto donde busco name no existe". La causa está en profile.js:8: hay que averiguar por qué ese objeto (por ejemplo, user.name donde user es undefined) llegó vacío — quizá un dato que no cargó, una respuesta de API sin ese campo, o una variable sin inicializar.

Por qué funciona: aplicaste la regla "lee siempre hacia la izquierda del punto". Este es uno de los mensajes mentirosos crónicos: es honesto sobre el síntoma pero apunta al lugar equivocado si lo lees literal.

Ejercicio 4 — Filtrar el log por severidad

Este es un fragmento de log de producción (los más nuevos abajo). ¿Qué línea lees primero y por qué? ¿Qué líneas puedes ignorar?

INFO  Server started on port 8080
INFO  Connected to database
ERROR Failed to load user cache: stale connection
WARN  Retrying database query (attempt 2)
ERROR Query failed: connection reset
ERROR Query failed: connection reset
Ver solución

Lees primero el primer ERROR en orden cronológico: ERROR Failed to load user cache: stale connection ("conexión rancia/desactualizada"). Ese es el fallo temprano que probablemente desató la cascada: la conexión ya estaba muerta, por eso vino el WARN Retrying y después los dos ERROR Query failed idénticos. Las dos líneas INFO son ruido de fondo saludable y se ignoran; los dos últimos ERROR repetidos son el eco del primero, no fallos independientes.

Por qué funciona: filtraste por severidad (ERROR/FATAL primero, INFO al final) y aplicaste la regla de la cascada: cuando ves errores idénticos repetidos, solo el primero cuenta; los demás son su eco.

Resumen y siguiente paso

Antes de avanzar a la próxima lección, deberías poder:

  • Reconocer las fórmulas fijas del dialecto (expected X, got Y, cannot, not found, refused, out of range, unexpected) sin traducirlas mentalmente.
  • Leer un stack trace por sus extremos: ir a la última línea para el qué y al primer marco de tu propio código para el dónde, saltándote los marcos de librerías.
  • Ordenar un log por severidad (DEBUGINFOWARNINGERRORCRITICAL/FATAL) y buscar el primer ERROR de una cascada en vez del último.
  • Desconfiar de los mensajes mentirosos (segfault, Cannot read property of undefined, Module not found, errores en cascada) tratando el texto como una primera hipótesis que se verifica en el código, no como veredicto final.

Si alguno de esos cuatro puntos todavía te cuesta, vuelve a la tabla de fórmulas y al ejemplo de stack trace y repite el Ejercicio 1 con un error real de tu propio código: esa es la práctica que fija el patrón.

En la próxima lección subimos un nivel de abstracción: del error que la máquina escribe sola, pasamos al texto que las personas escriben sobre el software — issues, changelogs y especificaciones. Ahí el inglés vuelve a ser humano, pero con sus propias convenciones. Lo que aprendiste aquí a citar un error con precisión será la materia prima del primer buen issue que escribas.

Recursos