Inicio·Mensajes de error

Mensajes de error, explicados

104 mensajes de error, con qué significan, por qué salieron y qué hacer.

Los arreglos tienen coste. git reset --hard descarta trabajo sin confirmar, un force push puede destruir los commits de otra persona y docker system prune borra volúmenes sin nombre. Donde ocurre, la ficha lo dice.

Git29

Casi todos los errores de git son una negativa que significa "hacer eso desde este estado perdería algo"; fatal: indica que git se detuvo sin cambiar nada, y las líneas hint: bajo la primera suelen traer el remedio real.

fatal: refusing to merge unrelated historiesLos dos lados que intentas fusionar no comparten ningún antepasado común, así que para git son dos proyectos ajenos entre sí. Suele salir cuando empezaste en local con git init, hiciste unos commits y luego añadiste un remoto que ya tenía commits propios e hiciste pull. --allow-unrelated-histories sí los fusiona, pero suelda dos historias ajenas en un único commit y separarlas después cuesta mucho; si solo tienes unos pocos commits locales, es más limpio clonar el remoto de nuevo y copiar tus archivos dentro.Your branch and 'origin/main' have divergedTu rama y origin/main tienen cada una commits que la otra no tiene: la línea de historia se ha partido en dos. Pasa cuando hiciste commits en local mientras otra persona hacía push, o cuando reescribiste con amend o rebase commits que ya habías subido. git pull --rebase vuelve a aplicar tus commits encima de los suyos y mantiene una sola línea, pero da hashes nuevos a tus commits, así que si ya los habías compartido el mismo trabajo queda registrado dos veces; en ese caso --no-rebase, que deja un único commit de fusión, es más seguro.fatal: Need to specify how to reconcile divergent branches.Desde git 2.34, pull no adivina si debe fusionar o hacer rebase cuando las ramas han divergido: pide una configuración, no avisa de una avería. Aparece cuando las ramas divergieron y nunca configuraste pull.rebase. pull.ff only es la respuesta más segura porque solo tira cuando puede avanzar y, si no, se detiene sin crear nada; pull.rebase true reescribe los hashes de tus commits locales cada vez, y false deja un commit de fusión.CONFLICT (content): Merge conflict in src/app.tsxAmbos lados cambiaron las mismas líneas de forma distinta y git no puede decidir cuál vale, así que escribió las dos versiones dentro del archivo entre <<<<<<<, ======= y >>>>>>> y se detuvo. Ocurre cuando tú y otra persona editáis la misma zona, o cuando un rebase pasa tu commit por encima de una edición de esas líneas. Abre el archivo, déjalo como debe quedar, borra los marcadores y luego haz git add y commit. git merge --abort te devuelve exactamente al estado anterior a la fusión, lo cual es seguro para todo lo ya confirmado, pero descarta las resoluciones que hubieras hecho a mano.Please commit your changes or stash them before you merge.Los archivos con cambios sin confirmar también los tocan los commits que llegan, y git prefirió detenerse antes que sobrescribirlos. Aparece cuando haces pull o merge con el árbol de trabajo sucio. git stash push -u aparta esos cambios para que la fusión pueda pasar, e -u incluye también los archivos sin seguimiento; pero git stash pop puede provocar conflicto al devolverlos, y un stash no se ve junto a tus ramas y es fácil de olvidar y perder, así que hacer un commit temporal es un hábito más seguro.error: Your local changes to the following files would be overwritten by checkout:Intentas cambiar de rama, pero archivos cuyo contenido allí es distinto siguen teniendo cambios que no has confirmado. Aparece cuando haces switch o checkout con el trabajo a medias. git stash push -u, o un commit temporal, te deja pasar y volver luego. El git checkout --force y el git switch --discard-changes que verás en los resultados de búsqueda sí te mueven, pero borran esos cambios sin confirmar para siempre: nada los registra, ni el reflog, así que no hay vuelta atrás.You are currently rebasing branch 'feature' on '8a3f21c'.Un rebase empezó y se detuvo a medias, y HEAD está aparcado en un estado temporal en lugar de en tu rama. Verás esta línea tras un conflicto durante el rebase, o tras una parada edit o break en git rebase -i, cuando te fuiste a hacer otra cosa sin terminarlo. Resuelve el conflicto, hazle git add y sigue con git rebase --continue, o usa --skip si quieres descartar ese commit. git rebase --abort te devuelve exactamente a donde estabas antes del rebase, así que no pierdes nada confirmado, pero se van con él las resoluciones hechas hasta ahora.You are in 'detached HEAD' state.HEAD apunta directamente a un commit en vez de a un nombre de rama, así que cualquier commit que hagas aquí no queda unido a ningún nombre. Se llega así al hacer checkout de un hash o de una etiqueta, al trabajar dentro de un submódulo, o porque CI hizo checkout de un commit concreto. Para conservar lo hecho, git switch -c nombre crea una rama justo aquí y no pierde nada. Si simplemente haces git switch main, los commits que creaste quedan sin nada que los señale: el reflog aún los encuentra un tiempo y luego la recolección de basura los borra.Warning: you are leaving 1 commit behind, not connected to any of your branches:Avisa de que hiciste commits en estado detached HEAD y ahora te vas, sin que ninguna rama apunte a esos commits. Ocurre cuando hiciste checkout de un hash, trabajaste, confirmaste y luego volviste a una rama. Usa el hash que aparece en el mensaje: git branch rescue 8a3f21c los fija a un nombre, y esa orden no cambia nada más, solo añade un nombre. Si ya te fuiste, git reflog todavía los lista, pero los commits a los que nada apunta se eliminan cuando pasa la recolección de basura, que por omisión es unos treinta días.error: failed to push some refs to 'https://github.com/user/repo.git'El servidor rechazó tu push y esta línea es solo el resumen: la razón real está en la línea ! [rejected] justo encima. Normalmente el remoto tiene commits que tú no tienes, pero una rama protegida, un hook del servidor o un límite de tamaño de archivo dan el mismo resumen. Lee primero la razón; para el caso corriente, git pull --rebase && git push lo resuelve. Lo peligroso es añadir --force sin leer, porque eso puede borrar del servidor los commits de un compañero.! [rejected] main -> main (fetch first)La rama remota tiene commits que tu clon nunca ha visto, así que hacer push ahora no sería un avance rápido. Pasa cuando un compañero hizo push antes, o cuando hace mucho que no haces fetch. git pull --rebase origin main trae esos commits y vuelve a aplicar los tuyos encima, y luego el push pasa. Nunca uses --force aquí: los commits que sobrescribirías son de otra persona y no están en tu repositorio, así que nada local puede recuperarlos.! [rejected] main -> main (non-fast-forward)Tu rama no es descendiente de la rama remota, así que hacer push tal cual dejaría fuera commits que existen en el servidor. Ocurre cuando reescribiste con rebase, amend o reset commits ya subidos. Si la reescritura fue intencionada y la rama es solo tuya, usa git push --force-with-lease: se niega si el remoto se movió desde tu último fetch, así que, a diferencia de --force sin más, no puede borrar en silencio el push de un compañero que llegó entremedias. Si no fue intencionada, la respuesta es pull --rebase, no forzar.Updates were rejected because the remote contains work that you do not have locally.Esta es la explicación detrás de un push rechazado: el remoto contiene trabajo que tu clon no tiene, y hacer push ahora lo eliminaría. Aparece cuando varias personas comparten una rama, o cuando editaste y confirmaste un archivo desde la web y nunca lo bajaste. Haz primero git pull --rebase origin main y luego push, y pasa sin más. Añadir --force a pesar de este aviso hace justo lo que el aviso pretende evitar: los commits de la otra persona desaparecen del servidor y, si nadie hizo fetch después de su push, no quedan en ninguna parte.error: src refspec main does not match anyEl nombre que pediste subir no existe en local ni como rama ni como etiqueta, y no se puede enviar lo que no está. Pasa en un repositorio recién creado sin commits, donde main aún no existe; o cuando tu rama local es master y escribiste main; o es simplemente una errata. git push -u origin HEAD sube la rama en la que realmente estás, con su nombre real, y resuelve de un golpe el caso del nombre equivocado. Si no hay ningún commit, haz uno primero: un repositorio vacío no tiene nada que enviar.fatal: The current branch feature has no upstream branch.Esta rama no tiene registrada una contraparte remota, así que un git push o git pull sin argumentos no sabe adónde ir. Pasa cuando creaste una rama con git switch -c y nunca la subiste. git push --set-upstream origin feature crea la rama en el servidor y registra el emparejamiento una sola vez; a partir de ahí basta con git push. La orden solo escribe una línea de configuración local y una rama nueva en el servidor, así que no borra nada y se puede repetir sin riesgo.error: cannot lock ref 'refs/remotes/origin/main': is at 8a3f21c but expected 1c2d3e4Cuando git iba a escribir un valor nuevo en una referencia de seguimiento remoto, encontró un valor distinto del que acababa de leer y se negó a sobrescribir. Suele pasar cuando tu editor hace fetch en segundo plano mientras tú también haces fetch, o cuando alguien hizo force push y tus referencias de seguimiento quedaron desajustadas. Repetir el fetch normalmente basta. git remote prune origin limpia las referencias de seguimiento cuyas ramas ya no existen arriba; borra solo las copias dentro de tu repositorio y nunca toca una rama del servidor.fatal: not a git repository (or any of the parent directories): .gitNo hay ningún .git en este directorio ni en ninguno por encima, así que git no encontró un repositorio. Pasa cuando estás un nivel por encima o por debajo del repositorio, cuando un clon acabó en otra carpeta, o cuando nunca ejecutaste git init. Comprueba primero dónde estás con pwd y usa git init solo si de verdad quieres empezar un repositorio aquí. Ejecutar git init dentro de una subcarpeta de un repositorio existente crea un segundo repositorio anidado que oculta en silencio al de fuera, y desde entonces los archivos de esa carpeta no entran en los commits externos.fatal: remote origin already exists.El nombre origin ya está en uso en este repositorio, así que no se puede crear otra vez. Un repositorio clonado tiene origin desde el principio, y el mensaje sale cuando sigues dentro de él una guía para repositorios nuevos y ejecutas git remote add origin. Mira primero adónde apunta origin con git remote -v; si lo que querías era otra URL, git remote set-url origin cambia solo el destino. Este ajuste es una línea de .git/config, reversible en cualquier momento y sin efecto sobre tus commits.error: pathspec 'featue' did not match any file(s) known to gitgit no encontró ningún archivo, rama ni etiqueta con ese nombre: la cadena entre comillas es exactamente lo que buscó. Pasa por una errata, porque la rama solo existe en el servidor y no has hecho fetch, o porque el archivo está en otro directorio del que suponías. Si es una rama, haz git fetch y luego git branch -a y compara el nombre con la vista; si es un archivo, git status --short muestra las rutas reales. Recuerda que las rutas de las órdenes de git se leen relativas al directorio donde estás, no a la raíz del repositorio, y eso solo ya explica muchos de estos casos.git@github.com: Permission denied (publickey).ssh llegó al servidor pero no ofreció ninguna clave que el servidor esté dispuesto a aceptar: es un problema de autenticación, no de red. Pasa cuando no has generado ninguna clave, cuando la tienes pero nunca la añadiste a ssh-agent, o cuando la clave pública no está registrada en tu cuenta de ese servicio. ssh-add ~/.ssh/id_ed25519 carga la clave en el agente durante esta sesión, y ssh -T git@github.com informa de qué clave se probó y como quién te reconoce. Ambas órdenes solo leen; no hay nada que perder.remote: Support for password authentication was removed on August 13, 2021.GitHub dejó de aceptar contraseñas de cuenta por https en 2021: tu contraseña no está mal, es el método el que ya no se acepta. Aparece cuando tu credencial guardada es una contraseña antigua, o cuando escribiste una en el aviso. Si quieres seguir con https, pon un personal access token en el campo de contraseña; si no, cambia a la dirección ssh con git remote set-url origin. Cambiar la dirección remota es una línea de configuración de tu propio clon, así que no toca ningún commit y se puede revertir en cualquier momento.fatal: Authentication failed for 'https://github.com/user/repo.git/'La credencial enviada fue rechazada: está mal, ha caducado, o es un token sin el alcance que este repositorio necesita. La trampa habitual es un token caducado que sigue en la caché del ayudante de credenciales: se envía sin preguntarte nada, así que sale la misma línea cada vez. La línea git credential reject del arreglo elimina solo esa entrada guardada para que se te vuelva a preguntar y puedas pegar un token nuevo. Solo borra la credencial guardada y no toca ningún dato del repositorio.fatal: Unable to create '/repo/.git/index.lock': File exists.git crea .git/index.lock como cerrojo mientras escribe el índice, así que si el archivo ya está, otro git se está ejecutando o uno murió y lo dejó. Lo deja un editor o IDE que ejecuta git en segundo plano, o una orden que interrumpiste con Ctrl+C o mataste. Asegúrate de que no hay ningún git en marcha y bórralo con rm -f .git/index.lock. Borrarlo mientras un proceso git trabaja de verdad puede corromper el índice, así que comprueba antes; si el índice queda mal, git reset lo reconstruye desde HEAD, y sin --hard no toca tus archivos.nothing to commit, working tree cleanNo es un error: git te dice que nada difiere del último commit, así que no hizo nada. Lo ves cuando el archivo que editaste lo captura .gitignore, cuando el sitio que editaste es otro clon o worktree distinto del que estás, o cuando ya lo confirmaste y lo olvidaste. git check-ignore -v <ruta> imprime la línea exacta de .gitignore que oculta un archivo, y git log -1 muestra si el cambio ya entró. Ambas órdenes solo leen.error: unable to unlink old 'dist/main.js': Permission deniedUn checkout quiso reemplazar un archivo por una versión nueva y el sistema operativo no dejó borrar el viejo. Pasa cuando otro programa lo tiene abierto, lo que es especialmente frecuente en Windows, o cuando no tienes permiso de escritura en el directorio. Cierra lo que lo retenga —servidor de desarrollo, editor, antivirus— y vuelve a ejecutar la misma orden; en Unix, arregla el permiso del directorio. Repetir la orden es seguro, pero ten en cuenta que git se detuvo a medias, así que el árbol de trabajo queda a medio actualizar hasta que funcione.fatal: bad object 8a3f21cEl nombre que diste no resuelve a nada que git pueda leer: o el objeto no está en este repositorio, o está y está dañado. Pasa con un hash copiado de otro clon o de un clon superficial, con un hash truncado demasiado corto, o con un objeto realmente corrupto tras un problema de disco. git fsck --full informa de objetos ausentes y rotos solo leyendo, y un hash ajeno necesita un git fetch antes de que el objeto exista aquí. Si fsck informa de corrupción, volver a clonar es más rápido y seguro que reparar: copia antes tus archivos sin confirmar a un lugar a salvo.warning: LF will be replaced by CRLF in package.json.Es un aviso, no un error: core.autocrlf está activo, así que git guarda LF en el commit pero escribirá CRLF en tu copia de trabajo. Instalar git en Windows con los valores por omisión pone autocrlf en true, así que sale en cada add en esa máquina. git config core.autocrlf input guarda LF y deja de convertir al extraer, y la mejor respuesta es un .gitattributes en el repositorio con * text=auto eol=lf, para que todos los clones se comporten igual. Cambiar el ajuste puede hacer que todos los archivos parezcan modificados una vez; eso es una única reextracción, no trabajo perdido.The file will have its original line endings in your working directoryEs la segunda mitad del aviso de CRLF anterior: dice que el archivo en disco conserva los finales de línea que ya tiene y que solo la copia guardada en el commit se normaliza. Viene del mismo ajuste autocrlf, así que por sí solo no hay nada roto. Pero si los diffs muestran archivos enteros cambiados, es señal de que los finales de línea del equipo difieren: fija la regla con un .gitattributes en el repositorio y ejecuta git add --renormalize . una vez. Esa orden reescribe solo cómo se almacenan los finales, no el contenido de los archivos.husky - pre-commit hook exited with code 1 (error)Tu commit nunca se creó: un hook —lint, pruebas, un formateador— terminó con código distinto de cero y git abortó. La razón real no está en esta línea, sino en la salida del propio hook justo encima, normalmente una regla de lint o un error de tipos. Arreglar lo que señaló el hook y volver a confirmar es la única respuesta real. git commit --no-verify se salta todos los hooks de commit y sí produce un commit, pero no ha pasado la comprobación: solo ha movido el fallo a CI, y el código sin formatear llega tal cual a tus compañeros.

npm20

En npm la causa está en la primera línea code XXXX y no en las seis últimas líneas npm ERR!, y cuando el fallo viene del árbol de dependencias o de una compilación nativa y no de tu código, borrar node_modules y reinstalar resuelve la mitad de los casos.

npm ERR! ERESOLVE unable to resolve dependency treeDesde npm 7 se aplican los rangos de peerDependencies, y esto dice que npm no encontró un conjunto de versiones que satisfaga todos a la vez. Es habitual cuando el paquete que instalas tiene un rango de peer que excluye la versión de react o typescript que ya tienes, sobre todo justo después de una subida de versión mayor. Lee las líneas Found: y Could not resolve: para ver quién exige qué y mueve una de las dos a una versión compatible: ese es el arreglo real. npm install --legacy-peer-deps instala ignorando por completo los rangos de peer, lo que te desatasca pero deja un árbol que los paquetes nunca aceptaron, así que los errores en ejecución por versiones descuadradas son tuyos.npm ERR! Conflicting peer dependency: react@18.3.1Esta línea señala el par que de verdad choca dentro del informe de ERESOLVE: este paquete exige esa versión de un peer mientras tu árbol tiene otra. Normalmente significa que la biblioteca principal subió de versión mayor y un plugin que la usa aún no se ha puesto al día. Preguntar por nombre con npm ls react imprime, en forma de árbol, quién pidió qué versión, y ahí mismo se ve cuál de los dos hay que mover. Actualizar el plugin es el arreglo real; --force escribe el árbol descuadrado de todos modos y esconde el problema hasta la ejecución.npm WARN react-dom@17.0.2 requires a peer of react@17.0.2 but none is installed.npm 6 solo avisaba de las dependencias peer y nunca las instalaba por ti: el paquete está, pero el compañero que dice necesitar no. Aparece en un proyecto que sigue en npm 6, o cuando usas un lockfile antiguo de aquella época. Instala tú mismo el peer indicado en una versión dentro del rango impreso y ya está. Todavía no ha fallado nada porque esto es solo un aviso, pero vuelve más tarde como Cannot find module, o como dos copias de la misma biblioteca dando errores sin sentido.npm WARN deprecated request@2.88.2: request has been deprecatedEl autor del paquete marcó esa versión como ya no recomendada: se instaló y sigue funcionando. Normalmente no es algo de tu propio package.json, sino una dependencia transitiva arrastrada por un paquete que sí usas. Preguntar por nombre con npm ls request muestra cuál de tus dependencias directas la trae, y el sitio donde arreglarlo es esa dependencia directa, no este paquete. Hoy no hay nada que hacer: deprecated no es una vulnerabilidad de seguridad, y de eso te informa npm audit.npm ERR! npm ci can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync.npm ci instala estrictamente lo que registra el lockfile, y se detuvo antes de empezar porque package.json pide algo que el lockfile no contiene. Pasa cuando alguien editó package.json a mano o resolvió un conflicto en él sin ejecutar install, o confirmó package.json sin el lockfile al lado. Ejecuta npm install en local una vez para que el lockfile cuadre y luego confirma el lockfile: eso es todo el arreglo. Borrar package-lock.json para salir del paso vuelve a resolver todas las dependencias a versiones más nuevas y cambia en silencio lo que contiene tu compilación.npm ERR! The `npm ci` command can only install with an existing package-lock.json or npm-shrinkwrap.jsonnpm ci no se ejecuta en absoluto sin lockfile, porque no tiene nada que le diga qué versiones instalar. Pasa cuando package-lock.json está en .gitignore, nunca se confirmó, o cuando el directorio donde estás no es la raíz del proyecto. npm install --package-lock-only escribe el lockfile sin instalar nada, y confirmarlo hace que CI funcione. Nunca pongas package-lock.json en .gitignore: la garantía de que CI compile lo mismo dos veces descansa en ese único archivo.npm ERR! Invalid Version:El campo version de package.json no es semver válido, así que npm no puede analizar el paquete en absoluto. Pasa con un valor editado a mano como 1.0 o v1.0.0 o una cadena vacía, sobre todo tras un conflicto mal resuelto en ese archivo. npm pkg set version=1.0.0 escribe de vuelta una versión de tres partes correcta. La orden edita solo package.json y no toca ni node_modules ni el lockfile, así que después toda orden que lea el archivo vuelve a funcionar de inmediato.npm ERR! 404 Not Found - GET https://registry.npmjs.org/@acme/ui - Not foundEl registro no tiene ningún paquete con ese nombre: un 404 es una respuesta sobre el nombre, no sobre tu red ni tus credenciales. Pasa por una errata, por un paquete que se despublicó, o por un scope privado en el que no has iniciado sesión. Un paquete privado se ve exactamente igual que uno inexistente para quien no tiene acceso, y por eso los tres casos caen en esta única línea. npm view @acme/ui version confirma si el nombre existe públicamente, y para un scope privado comprueba que .npmrc tenga el registro y el token de ese scope. Ambas comprobaciones solo leen.npm ERR! request to https://registry.npmjs.org/express failed, reason: unable to verify the first certificateLa conexión TLS falló: la cadena de certificados que presentó el servidor sube hasta una autoridad en la que node no confía. De forma abrumadora es una red corporativa cuyo proxy abre el tráfico y lo vuelve a firmar con su propio certificado; a veces es un servidor que no envió su certificado intermedio. Enseñarle a npm la raíz de tu empresa con npm config set cafile es el arreglo correcto. strict-ssl false también hace desaparecer esta línea, pero desactiva por completo la comprobación de certificados, lo que permite que cualquiera en el camino te sirva paquetes alterados: no lo uses.npm ERR! code EINTEGRITYEl hash del tarball que npm descargó no coincide con lo que registra el lockfile, así que npm decidió que no puede confiar en lo que llegó y se detuvo. Es una entrada de caché corrupta, o un proxy que modificó la descarga, o más raramente un lockfile cuyo valor integrity se editó a mano o se fusionó mal. npm cache clean --force vacía la caché local para que la siguiente instalación vuelva a descargar; borra solo copias en caché y se puede repetir sin riesgo. Si sigue pasando con un paquete concreto, el propio valor integrity registrado está mal y esa entrada hay que volver a resolverla con npm install.npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'npm intentó escribir en un directorio del sistema que tu usuario no posee: el paquete está bien, simplemente no tienes derecho a escribir ahí. Casi siempre es npm install -g contra un node que el gestor de paquetes del sistema puso en un sitio como /usr/local. npm config set prefix ~/.npm-global traslada las instalaciones globales a tu directorio personal y, con su bin en el PATH, el error no vuelve. sudo npm install -g funciona, pero deja archivos propiedad de root en la caché y en node_modules que producen el mismo EACCES en instalaciones normales más adelante; un gestor de versiones como nvm elimina toda esta clase de problema.npm ERR! enoent ENOENT: no such file or directory, open '/home/me/package.json'npm buscó package.json en el directorio actual y hacia arriba y no encontró ninguno: ejecutaste una orden de npm en un sitio que no es un proyecto. Pasa cuando estás en la raíz de un monorepo y el proyecto está en una subcarpeta, cuando estás al lado de la carpeta que clonaste, o cuando simplemente olvidaste hacer cd. La respuesta es moverte a la carpeta que tiene package.json, y un ls es la forma más rápida de verlo. Usa npm init -y solo si de verdad quieres empezar un proyecto nuevo aquí: en la carpeta equivocada deja un package.json suelto que luego confunde a las herramientas.npm ERR! code ELIFECYCLEUn script de package.json terminó con un código distinto de cero: ELIFECYCLE es la envoltura de npm alrededor de eso, no la causa. La causa es lo que hizo tu script de compilación o de pruebas, y las líneas del error real están por encima de esta. Sube hasta el primer error, o ejecuta a mano la orden real impresa tras npm ERR! <pkg>@<ver> <script>: para ver su salida sin la envoltura de npm. El código de salida que sigue también dice algo: 1 es un fallo normal, mientras que 137 significa que el proceso fue matado, típicamente por memoria.gyp ERR! build errorUna dependencia contiene C o C++ que debe compilarse en tu máquina al instalar, y esa compilación falló: node-gyp necesita un compilador y python. Pasa cuando no hay ninguna cadena de compilación instalada, o cuando el paquete es más antiguo que tu node y las cabeceras ya no encajan. Instala las herramientas: xcode-select --install para las herramientas de línea de órdenes en macOS, build-essential y python3 en Debian o Ubuntu, la carga de trabajo de C++ de Visual Studio en Windows. Si una versión más nueva del paquete trae un binario precompilado para tu node, subir el paquete es mucho más rápido que arreglar el entorno de compilación.Error: Cannot find module 'express'node no pudo resolver ese nombre a ningún archivo: no está en node_modules, o ejecutaste desde un directorio sin node_modules. Pasa cuando nunca instalaste, cuando una instalación falló a medias y dejó un árbol parcial, o cuando el paquete está en devDependencies y instalaste con --omit=dev. rm -rf node_modules && npm install reconstruye el árbol desde el lockfile; es seguro, no pierde nada y solo cuesta el tiempo de descarga. Pero si el nombre entre comillas es una ruta relativa que empieza por ./, no falta ningún paquete: la ruta de tu propio código está mal.Module not found: Error: Can't resolve './components/Button' in '/app/src'El empaquetador no encontró ese archivo en esa ruta: esto es tu propio import, no un paquete. Pasa cuando la ruta relativa está desviada un nivel, cuando falta la extensión o es incorrecta, o cuando las mayúsculas del nombre del archivo difieren del import. Lo último es lo más traicionero: los sistemas de archivos de macOS y Windows no distinguen mayúsculas, así que funciona en tu máquina y solo se rompe en el CI de Linux. Haz ls del directorio y compáralo con el import carácter a carácter, mayúsculas incluidas. Si el nombre es un paquete y no una ruta, instálalo; en ningún caso se borra nada.Error: error:0308010C:digital envelope routines::unsupportednode 17 incorporó OpenSSL 3, que quitó de los valores por omisión un algoritmo de hash antiguo, y una herramienta que sigue pidiéndolo se cae justo dentro de esa llamada. Casi siempre es un webpack 4 viejo, o una herramienta que lo lleva dentro, corriendo sobre un node moderno. export NODE_OPTIONS=--openssl-legacy-provider vuelve a habilitar los algoritmos antiguos para ese proceso y es inocuo para una compilación. Pero eso mantiene con vida una herramienta muerta: subir a webpack 5, o a la versión actual de tu framework, elimina por completo la necesidad de la opción.FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryEl montón de V8 llegó a su techo y node se rindió por sí mismo: el sistema operativo no lo mató, node decidió que no podía crecer más y se detuvo. La causa es una comprobación de tipos o un empaquetado grande, una compilación con source maps en un proyecto grande, o código con fugas como acumular todo en un array. export NODE_OPTIONS=--max-old-space-size=4096 sube el techo a 4 GB y a menudo basta, pero la máquina tiene que tener de verdad esa RAM, y si el límite de un contenedor es menor, el sistema operativo mata el proceso, lo que aparece como código de salida 137. Si el número tiene que crecer una y otra vez, la causa es una fuga y no el límite.npm WARN EBADENGINE Unsupported engineAlgún paquete declara un rango de engines para node o npm que tu entorno no satisface: npm solo avisa e instala igualmente. Pasa cuando usas un node antiguo instalado como paquete del sistema, o cuando el proyecto pasó a un node más nuevo que el de tu shell. Cambia node a una versión dentro del rango impreso con tu gestor de versiones; lo que hay que creer es el .nvmrc del proyecto o el campo engines de package.json. Por omisión es solo un aviso, pero con engine-strict=true en .npmrc la misma condición se convierte en un error que detiene la instalación.zsh: command not found: tscEl shell recorrió el PATH y no encontró ningún ejecutable con ese nombre: puede que la instalación sí haya funcionado. Pasa cuando el directorio bin global de npm no está en el PATH, cuando instalaste en local y no en global y el binario acabó en node_modules/.bin, o cuando el shell tiene un PATH antiguo en su caché. npx tsc --version ejecuta la copia local sin tocar el PATH, así que esa única línea separa no instalado de no está en el PATH. Para una instalación realmente global, añade al PATH la salida de npm prefix -g más /bin y abre un shell nuevo.

JavaScript15

Los errores del navegador y de Node suelen decirte qué se rompió y no por qué el valor llegó a ser así —leíste undefined, no era una función, no era JSON—, así que el lugar del arreglo está aguas arriba de la línea que lanzó el error, y silenciar solo esa línea con ?. y valores por defecto hace que el mismo problema reaparezca más lejos y con una forma más difícil de reconocer.

Uncaught TypeError: Cannot read properties of undefined (reading 'name')El valor a la izquierda del punto es undefined y le leíste una propiedad; el nombre entre paréntesis es la propiedad que querías, así que lo roto es el valor anterior. Viene de una respuesta que aún no ha llegado, de una prop que nadie pasó, de un nivel de más como en data.user.name, o de arr[0].id sobre un array vacío. Cuando el valor es legítimamente opcional, user?.name corta el paso; pero si el valor debía estar ahí, ?. solo convierte el error en un undefined que falla en la línea siguiente, así que busca arriba por qué es undefined. Antes de Chrome 78 el mismo error decía Cannot read property 'name' of undefined.TypeError: items.map is not a functionEl nombre existe pero no es una función; si no existiera en absoluto, el mensaje hablaría de undefined. Las causas típicas son algo que tomaste por un array y en realidad es un objeto o un NodeList, una API que devuelve {data: [...]} en vez del array, o una exportación por defecto con otra forma. Imprímelo antes de teorizar: un solo console.log(typeof items, items) resuelve la mitad de estos casos al instante. Un NodeList o un Set solo necesitan Array.from(items); pero si era {data: [...]}, envolverlo está mal y lo correcto es items = res.data.RangeError: Maximum call stack size exceededLas llamadas se apilaron más de lo que permite el motor, y normalmente no es recursión profunda sino recursión sin fin. Una función cuya condición de parada falta o nunca se alcanza, dos funciones que se llaman entre sí, JSON.stringify sobre un objeto que se contiene a sí mismo, o en React un render que cambia el estado del que depende. La pila de la consola repite dos o tres marcos: ese par es el bucle, y ahí va el caso base. Si el cálculo necesita profundidad de verdad, reescribir la recursión como bucle o pila explícita es el único camino: en un navegador no puedes subir el límite de pila.SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSONLo que le pasaste a JSON.parse era HTML, no JSON. El fragmento <!DOCTYPE citado en el mensaje es la prueba, y significa que el servidor respondió con una página HTML —un 404, un 502 o una redirección de inicio de sesión—, así que el error real está antes del análisis, en la petición. Causas típicas: la URL equivocada, un proxy del servidor de desarrollo que sirvió index.html en lugar de la API, o una sesión caducada que te redirigió al login. Comprueba res.ok antes de llamar a res.json() y lee res.text() para ver qué llegó de verdad; golpear la URL con curl -s es la forma más rápida de mirar. Antes de Chrome 111 y Node 20 el mismo error decía Unexpected token < in JSON at position 0.SyntaxError: Unexpected end of JSON inputEl analizador llegó al final del documento mientras aún leía JSON y, casi siempre, el cuerpo estaba simplemente vacío. Llamar a res.json() sobre un 204 No Content o sobre una respuesta de error sin cuerpo, leer el cuerpo dos veces de modo que la segunda vuelve vacío, o leer un archivo truncado a medio escribir. Toma el texto primero y compruébalo antes de analizar —const t = await res.text(); if (!t) return null;—, que da un diagnóstico exacto. Taparlo con JSON.parse(text || 'null') hace que una respuesta vacía parezca normal, así que averigua antes por qué el servidor envió un cuerpo vacío.TypeError: Failed to fetchLa petición terminó sin respuesta, y el navegador oculta el motivo a propósito: un bloqueo CORS, una dirección muerta, un certificado inválido y una extensión que bloquea anuncios producen las mismas dos palabras. Es un error lanzado, no un estado, así que un 404 o un 500 nunca llega aquí: el servidor ni empezó a responder. Suele haber una segunda línea más concreta justo encima en la consola o en la pestaña Network, así que léela primero; y golpear la URL con curl -i separa "el servidor está caído" de "el navegador se negó". Firefox expresa lo mismo como NetworkError when attempting to fetch resource.Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.La petición llegó al servidor y volvió una respuesta, pero esa respuesta no traía ninguna cabecera que permita este origen, así que el navegador se negó a entregársela a tu JavaScript. Solo los navegadores aplican esta regla, y por eso la misma URL funciona desde curl: parece que el servidor está bien y que solo el navegador falla. El arreglo vive siempre en el servidor: añade Access-Control-Allow-Origin: http://localhost:3000 a la respuesta. El frontend no puede hacer nada, y si el servidor no es tuyo, pasar la llamada por uno propio es el único camino. Allow-Origin: * no sirve para peticiones que envían cookies; esas necesitan el origen exacto y además Allow-Credentials.SyntaxError: Cannot use import statement outside a moduleNode o el navegador leyeron ese archivo como un script CommonJS, y dentro había la palabra clave ESM import. Un archivo .js es CommonJS salvo que package.json diga lo contrario, y en el navegador ocurre lo mismo cuando la etiqueta <script> no lleva type="module". npm pkg set type=module declara todo el paquete como ESM y lo resuelve, pero desde ese momento cada .js del paquete pierde require y __dirname, así que los archivos CommonJS restantes también tienen que migrar; si solo quieres convertir un archivo, renombrarlo a .mjs es el cambio más estrecho y seguro.ReferenceError: require is not defined in ES module scope, you can use import insteadEste es el espejo exacto del error anterior: el archivo se lee como ESM y contiene el require de CommonJS. Ocurre casi siempre justo después de añadir "type": "module" a package.json cuando aún quedan scripts antiguos en el árbol. Para dejar ese archivo en el mundo viejo, mv script.js script.cjs es el cambio más pequeño; para migrarlo, reescribir require como import implica también resolver __dirname y require.main === module, que no existen en ESM.Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/src/util' imported from /app/src/index.jsCuando Node ejecuta ESM trata las rutas de import como nombres de archivo literales, igual que un navegador, así que './util' no es './util.js': es un archivo que no existe. CommonJS probaba extensiones por ti, y TypeScript deja los import sin extensión intactos al compilar, por lo que un proyecto compilado con tsc lanza un montón de estos la primera vez que lo ejecutas con node. Añade la extensión .js a los import relativos; dentro de un archivo TypeScript también se escribe './util.js', porque lo que Node leerá es la salida compilada. Los nombres de paquetes de node_modules no llevan extensión.ReferenceError: window is not definedEl código se ejecutó dentro de Node en el servidor, no en un navegador. Node no tiene window, ni document, ni localStorage, así que tocar window mientras se carga un módulo en un framework que primero renderiza en servidor, como Next.js o Nuxt, se detiene aquí: a menudo es una sola línea fuera del componente, o el propio import de una biblioteca solo para navegador. Si el trabajo es solo de navegador, protégelo con typeof window !== 'undefined' o, mejor, muévelo dentro de useEffect, que solo se ejecuta en el navegador. Cuando toda una biblioteca es solo de navegador, Next.js puede excluirla del render del servidor con dynamic(() => import('./C'), { ssr: false }), a costa de que esa parte no aparezca en el HTML renderizado en servidor.Hydration failed because the initial UI does not match what was rendered on the serverEl HTML que envió el servidor y lo que el navegador produjo en su primer render son distintos, así que React no pudo unir uno con otro. Usar new Date() o Math.random() durante el render, leer localStorage o dibujar según el ancho de window garantiza dos respuestas diferentes; y también lo hace un marcado que el navegador repara en silencio, como un <div> dentro de un <p>. La regla es renderizar en la primera pasada exactamente lo que renderizó el servidor y cambiarlo después de que useEffect se ejecute; el precio es que esa parte aparece un instante más tarde y no está en el HTML del servidor. React 19 expresa lo mismo como "the server rendered HTML didn't match the client" e imprime un diff de lo que difería.Objects are not valid as a React child (found: object with keys {name, id})El valor que pediste renderizar es un objeto y no una cadena o un número, y la lista de claves entre paréntesis te dice qué objeto es. Normalmente la línea debería decir {user.name} donde dice {user}, o intentaste renderizar una respuesta completa. Si en vez de una lista de claves ves found: [object Promise], la causa es otra: renderizaste el resultado de una función async sin esperarlo. La solución es elegir el campo a mostrar; JSON.stringify(user) sirve para un vistazo rápido mientras depuras, pero no lo dejes en pantalla.Each child in a list should have a unique "key" prop.Los elementos hermanos renderizados como lista no tienen key, así que React no puede emparejarlos con los mismos elementos en el siguiente render. Construiste los elementos con items.map(...) y omitiste key; es solo una advertencia, la pantalla se dibuja, pero vuelve como un fallo silencioso cuando la lista cambia: el síntoma es el valor de un input o una animación que se queda en la fila equivocada. Dale un id estable de tus datos. Usar el índice del array como key solo es seguro en una lista cuyo orden nunca cambia y donde nada se inserta ni se borra en medio; si no, reproduce casi exactamente el problema de no tener key. Desde React 19 ya no aparece el Warning: inicial.Too many re-renders. React limits the number of renders to prevent an infinite loop.Un render cambió el estado, ese estado provocó otro render, y React cortó el ciclo para evitar uno infinito. Casi siempre es una función invocada donde debía pasarse: onClick={setOpen(true)} se ejecuta en cada render, y tiene que ser onClick={() => setOpen(true)}. Las otras formas habituales son cambiar el estado directamente en el cuerpo del render, y un useEffect cuya lista de dependencias contiene el valor que él mismo actualiza. Mueve los cambios de estado a un manejador de eventos o a un useEffect, y si el valor se puede calcular durante el render, pregúntate si necesita ser estado.

Python18

Un traceback de Python divide la respuesta en dos: la última línea dice qué falló y los marcos de arriba dicen dónde, así que leer solo la última línea te da el nombre y te quita el lugar; y en los errores por valor ausente, como NoneType y KeyError, la causa casi siempre está en un marco superior al que se rompió.

ModuleNotFoundError: No module named 'requests'Python recorrió todos los directorios de sys.path y no encontró ningún módulo con ese nombre. O no se instaló nunca, o se instaló para otro intérprete: hacer pip install fuera de un entorno virtual y ejecutar dentro de él produce justo esto. Escribirlo como python -m pip install lo instala en el intérprete que estás ejecutando de verdad, y así desaparece el desajuste.error: externally-managed-environmentEste Python pertenece al sistema operativo o a Homebrew, y pip se niega a escribir en él (PEP 668). Has hecho pip install contra el intérprete del sistema; el mensaje te está pidiendo crear un entorno virtual. --break-system-packages hace lo que su nombre indica y puede dejar en mal estado archivos gestionados por apt, así que crea un .venv e instala ahí.ImportError: cannot import name 'User' from partially initialized module 'models' (most likely due to a circular import)Dos módulos se importan mutuamente, así que pediste un nombre a un módulo que solo está medio cargado. Surge de la forma A importa B y B importa A, y es habitual justo tras dividir un archivo cuando una anotación de tipo devuelve el import al otro lado. Cambia from y import Thing por import y y usa y.Thing dentro de la función: la búsqueda ocurre más tarde y el ciclo deja de importar.IndentationError: unexpected indentLa línea está más indentada que la anterior y nada por encima abrió un bloque que justifique ese nivel extra. Normalmente pegaste código que traía sus propios espacios, o borraste una línea if y dejaste su cuerpo indentado bajo nada. Quita el espacio inicial de la línea que señala el error; si no ves la diferencia, imprime esa línea con cat -A y los espacios y tabuladores se hacen visibles.TabError: inconsistent use of tabs and spaces in indentationSe mezclan tabuladores y espacios dentro de un mismo bloque, así que Python no puede decidir qué línea está más adentro. Ocurre al pegar desde un editor que inserta tabuladores, o cuando dos personas editan el mismo archivo con ajustes distintos; en pantalla las líneas se ven iguales, así que no lo encontrarás a ojo. python -m tabnanny app.py imprime los números de línea culpables, y el resto es pasar todo el archivo a cuatro espacios en tu editor.SyntaxError: invalid syntaxEl analizador no pudo formar una sentencia con lo que encontró ahí, y la causa suele estar en la línea anterior a la que señala, no en esa misma. Un paréntesis o una comilla sin cerrar, dos puntos que faltan o el print "x" de Python 2 son las causas habituales: con un paréntesis abierto el analizador avanza varias líneas antes de rendirse. python -m py_compile app.py comprueba la sintaxis sin ejecutar nada, y desde 3.10 los mensajes son mucho más precisos, así que actualizar Python ya es un diagnóstico.TypeError: 'NoneType' object is not subscriptableEl valor que intentaste indexar con [...] es None. Algo más arriba devolvió None en silencio: un dict.get() con una clave ausente, un re.match que no coincidió, o una función sin return en el camino que se ejecutó. En vez de proteger el punto del fallo, sube y averigua por qué es None: un if que se salta el None solo traslada el mismo error a la línea siguiente.AttributeError: 'NoneType' object has no attribute 'get'El objeto a la izquierda del punto es None, así que el atributo o método que pediste no existe. Tiene la misma raíz que nonetype-not-subscriptable y aparece sobre todo al encadenar directamente el resultado de una función que devuelve None al fallar, como find() de BeautifulSoup o re.search(). Imprime primero qué estaba buscando esa función y, si no encontrar nada es un caso válido, trata esa rama de forma explícita.KeyError: 'name'La clave no está en el dict, y el texto entre comillas es justo la clave que buscó: empieza por ahí, porque suele ser un error de tecleo, una diferencia de mayúsculas, o una respuesta de API cuya forma no es la que suponías. Si el valor es realmente opcional, d.get("name") devuelve None y d.get("name", 0) da un valor por defecto; pero usar .get en un valor obligatorio cambia el error por un None que viaja por tu código y estalla mucho más lejos.IndexError: list index out of rangePediste una posición que la lista no tiene. Con longitud n el último índice válido es n-1, así que range(len(x) + 1) y x[len(x)] siempre paran aquí, y x[0] sobre una lista vacía es el mismo error, algo habitual cuando un filtro o un split anterior no dejó nada. Recorrerla como for item in items: elimina de raíz esta clase de fallo, y si de verdad necesitas la posición, enumerate(items) te la da.ValueError: invalid literal for int() with base 10: '3.5'Le pasaste a int() una cadena que no puede leer como número entero, y el texto entre comillas es esa cadena. Un punto decimal como en '3.5', una cadena vacía, una entrada con salto de línea al final o un separador de miles como en '1,000' son las causas habituales. Para un decimal, int(float(s)) funciona en dos pasos, pero corta la parte fraccionaria en lugar de redondear; y para cualquier valor tecleado por una persona, envolverlo en try/except ValueError es la solución honesta.UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byteLeíste un archivo o una secuencia de bytes como UTF-8 y apareció un byte que UTF-8 no permite; el mensaje indica la posición y el byte. Lo normal es que el archivo sea cp1252 u otra codificación heredada de Windows, o que no sea texto en absoluto: una imagen, un zip o datos gzip sin descomprimir. Lo correcto es averiguar la codificación real y pasarla en encoding=; errors="replace" permite terminar la lectura pero convierte esos bytes en signos de interrogación, y los datos quedan dañados en silencio.ZeroDivisionError: division by zeroAlgo se dividió por cero y, en la práctica, el divisor casi nunca es un cero literal: es un recuento que salió cero. Un código que calcula una media cuando la lista quedó vacía, o un filtro que no encontró nada, es la fuente clásica: pasa con tus datos de desarrollo y falla por primera vez en producción. Comprueba el denominador antes de dividir y decide qué significa cero ahí; devolver 0, devolver None o dejar que la excepción suba son tres decisiones distintas, y cada una es correcta en algún caso.RecursionError: maximum recursion depth exceededUna función se llamó a sí misma más profundo que el límite predeterminado de 1000 marcos. Mucho más a menudo que un cálculo realmente profundo, esto significa que falta la condición de parada o nunca se alcanza; la recursión indirecta también cuenta, como un __getattr__ o una property que vuelve a leer su propio atributo. Busca los dos o tres marcos que se repiten en el traceback y corrige primero el caso base. sys.setrecursionlimit() sube el techo, pero permite desbordar la pila real de C, y entonces Python muere de golpe en lugar de lanzar una excepción: reescribir la recursión como un bucle es la respuesta segura.UnboundLocalError: cannot access local variable 'count' where it is not associated with a valueSi una función asigna a un nombre en cualquier parte de su cuerpo, Python lo considera local a la función, y tú lo leíste antes de que la asignación se ejecutara. Aparece cuando esperabas ver el valor exterior con ese mismo nombre, o la primera vez que escribes una operación de lectura y escritura como count += 1. Inicializarlo dentro de la función con count = 0 es la respuesta habitual; si de verdad necesitas cambiar el valor a nivel de módulo, global count lo hace, al precio de un valor cuyos escritores se vuelven difíciles de rastrear. Hasta la 3.10 el mismo error decía 'local variable referenced before assignment'.TypeError: greet() takes 1 positional argument but 2 were givenPasaste un argumento más de los que la función acepta, y cuando los números difieren exactamente en uno casi siempre es self. Si defines un método dentro de una clase como def greet(name):, al llamar obj.greet("x") Python envía obj como primer argumento y ya van dos. Si es un método, cámbialo a def greet(self, name): para que reciba self; si no necesita la instancia, márcalo con @staticmethod.PermissionError: [Errno 13] Permission deniedEl sistema operativo rechazó esa operación sobre esa ruta. Estabas escribiendo en un lugar propiedad de otro, como /var/log o /usr, o en un volumen montado en un contenedor cuyo UID no coincide con el usuario del contenedor, o —el caso que se pasa por alto— no tienes permiso de escritura en el directorio y no en el archivo, que es lo que hace falta para crear uno nuevo. Comprueba primero propietario y modo con ls -ld y, antes de recurrir a sudo, considera mover la ruta a un lugar donde sí puedas escribir: un archivo creado con sudo dará el mismo error la próxima vez que lo abras sin sudo.OSError: [Errno 98] Address already in useEl bind falló porque otro proceso ya tiene ese puerto. O el servidor anterior no murió del todo, o un recargador automático levantó dos copias, o un contenedor Docker ya publica el mismo puerto. lsof -i :8000 te da el PID que lo retiene, para limpiar solo ese; lee el nombre del proceso antes de hacer kill -9 a nada. El errno cambia según el sistema: Linux imprime 98 aquí y macOS imprime 48.

Compilación y tipos10

Los errores de compilación son una herramienta que se niega antes de que nada se ejecute, así que no rompen nada en el momento en que aparecen, pero plantean dos preguntas: ¿arreglarás el tipo o la ruta para que coincidan con la forma real, o empujarás esa única línea con un as any o un comentario de supresión? Y es aquí donde las cosas que solo son ciertas en tu máquina —mayúsculas, extensiones y variables de entorno— se muestran por primera vez.

error TS2307: Cannot find module 'lodash' or its corresponding type declarations.tsc no encontró ni el módulo ni ninguna declaración de tipos para él, y es importante que el mensaje diga ambas cosas: puede que el paquete no esté, o que esté instalado sin tipos. Si está instalado, lo que falta son los tipos: npm i -D @types/lodash añade el paquete acompañante, aunque muchos paquetes modernos incluyen sus propios tipos y no tienen @types. Cuando esto salta en un import relativo, mira las mayúsculas y las paths de tsconfig: una ruta a tus propios archivos no tiene nada que ver con @types.error TS2339: Property 'user' does not exist on type 'Request'.Ese tipo no declara esa propiedad. Aparece al añadir un campo que el tipo de la biblioteca no tiene (el clásico es colgar user del Request de Express), por una errata, o al leer una propiedad que solo existe en un miembro de una unión sin estrechar. Corregir el tipo para que coincida con la forma real es la respuesta, y en una unión, estrechar con 'x' in y o con un campo discriminante abre el acceso dentro de la rama. Silenciarlo con as any solo amordaza al compilador: ese punto aceptará también un nombre de propiedad mal escrito.error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.El tipo que la función acepta y el tipo que pasaste son distintos, y el mensaje los nombra en orden: primero lo que diste, después lo que quería. El caso más frecuente con diferencia es un valor de un campo de formulario, de la cadena de consulta de una URL o de JSON que llega como texto donde se espera un número. Convertir una vez en la frontera es la respuesta, pero Number(value) devuelve NaN en vez de lanzar cuando falla, así que hay que impedir que ese NaN siga viajando: Number.isFinite(n) es la comprobación que corresponde.error TS18048: 'user' is possibly 'undefined'.El valor puede ser undefined y no has tratado esa posibilidad; esto es tsc atrapando por ti un futuro Cannot read properties of undefined. Aparece en campos opcionales, en el resultado de un find() de array y en variables de entorno que podrían no estar definidas. La solución es decidir qué pasa cuando falta: corta pronto con if (!user) return null, o cortocircuita con user?.name. Silenciarlo como user!.name es declarar que tú lo garantizas, y cuando la garantía es falsa vuelve como excepción en ejecución, sin nada de la red de seguridad que habría dejado una comprobación.error TS7006: Parameter 'req' implicitly has an 'any' type.El parámetro no lleva tipo escrito y tsc no tenía de dónde inferirlo, así que pasó a ser any de forma implícita, y noImplicitAny lo considera un error. Aparece en archivos migrados de JavaScript y cuando se extrae un callback a su propia variable; en cambio, un callback escrito en línea como items.map(x => ...) tiene contexto y tsc lo infiere, así que esto no salta. Escribir el tipo ahí es la solución. También puedes poner any explícitamente, pero eso es decidir apagar la comprobación por completo en ese parámetro: cuando no sabes qué es, unknown es más honesto y te obliga a estrechar antes de usarlo.Parsing error: Unexpected tokenESLint se detuvo mientras leía la sintaxis, antes de aplicar ninguna regla al archivo. Mucho más a menudo que un código realmente roto, esto significa que el analizador no conoce esa sintaxis: un archivo TypeScript leído por el analizador por defecto, JSX que nunca se activó, o decoradores y sintaxis muy nueva entregados a un analizador antiguo. Ejecutar npx eslint --print-config app.ts sobre ese archivo exacto imprime qué parser y qué parserOptions se aplican de verdad, así que empieza por ahí en vez de adivinar. TypeScript necesita @typescript-eslint/parser, y si el archivo no debería analizarse, listarlo en ignores es la respuesta correcta.You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.Esta es la línea que webpack añade tras Module parse failed, y significa que intentó leer ese archivo como JavaScript y no lo era. O importaste algo que necesita transformación —TypeScript, JSX, CSS, una imagen, un archivo .vue— sin ninguna regla en module.rules, o un paquete de node_modules publica fuente sin compilar mientras esa carpeta está en tu exclude. La solución es añadir una regla de loader para esa extensión en module.rules, y la ruta impresa encima del mensaje te dice qué archivo lo detuvo. Borrar exclude: /node_modules/ para que desaparezca ralentiza notablemente toda la compilación; excluir solo ese paquete es el mejor cambio.Failed to resolve import "./utils" from "src/main.ts". Does the file exist?No se encontró nada en esa ruta, y el "Does the file exist?" que imprime apunta a las tres cosas que de verdad hay que revisar: las mayúsculas, la extensión y cualquier alias en tsconfig o vite.config. Los sistemas de archivos de macOS y Windows ignoran las mayúsculas, así que ./Utils funciona en tu máquina y falla por primera vez en CI o en el despliegue, donde Linux sí distingue: este error es la identidad más común de "pero en mi máquina funciona". git ls-files src | grep -i utils muestra con qué grafía está realmente en el repositorio. Para un alias como @/utils, resolve.alias de vite.config y paths de tsconfig deben coincidir; si arreglas solo uno, el editor calla y la compilación sigue rota.You're importing a component that needs useState. This React hook only works in a client component.En el App Router todo componente es un componente de servidor por defecto, y un componente de servidor importó un archivo que usa un hook que solo tiene sentido en el navegador, como useState. La directiva es una sola línea 'use client' arriba del archivo, y añadirla arrastra ese archivo y todo lo que importa al paquete del cliente: por eso marcar la pieza más pequeña que necesita estado, y no la página entera, es la opción barata. En sentido inverso, dividir de modo que un componente de cliente reciba componentes de servidor como hijos mantiene la obtención de datos en el servidor. Next.js 13 expresaba lo mismo como "It only works in a Client Component but none of its parents are marked with \"use client\"".The engine "node" is incompatible with this module. Expected version ">=20"El paquete que instalas declara en el campo engines las versiones de Node que necesita, y la que usas queda fuera de ese rango. El Expected y el Got que siguen ponen el requisito y tu versión lado a lado, así que con esas dos líneas basta; y si esto solo pasa en CI, su versión de Node difiere de la de tu máquina. Actualizar con nvm install 20 && nvm use 20 es la respuesta directa, y escribir la misma versión en .nvmrc y en la configuración de CI evita que vuelvan a separarse. El --ignore-engines de yarn te deja pasar, pero borra el aviso en lugar de crear compatibilidad: si el paquete usa sintaxis nueva, fallará en ejecución con un error de sintaxis. npm informa lo mismo como un aviso EBADENGINE y por defecto no impide la instalación.

Docker12

Los errores de Docker solo se vuelven legibles cuando los sitúas en una capa —el cliente que no alcanza al demonio, el registro que te rechaza, un RUN que falla durante la compilación y un contenedor que muere al arrancar son cuatro problemas distintos— y en las capas de compilación y ejecución la línea en sí no es el motivo: el motivo está en la salida del comando que corría dentro, y el precio de cada arreglo también cambia según la capa.

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?El comando docker no hace nada por sí mismo: pide al demonio a través de ese socket, y nadie respondió. O el demonio no está en marcha, o Docker Desktop aún no ha terminado de arrancar en macOS o Windows, o en Linux tu usuario no está en el grupo docker y no puede abrir el socket; los tres casos dan esta misma línea. En Linux arráncalo con sudo systemctl start docker; con Desktop, abre primero la aplicación. Si es cuestión de permisos, sudo usermod -aG docker $USER y volver a iniciar sesión lo resuelve, pero ese grupo equivale en la práctica a root.Bind for 0.0.0.0:8080 failed: port is already allocatedPediste ese puerto del host con -p y otro contenedor o proceso ya lo tiene. Lo más común es que un contenedor que lanzaste antes sin --rm siga ahí, parado o en marcha, o que compose siga reteniendo uno anterior. docker ps --filter publish=8080 señala directamente al contenedor que lo publica; si resulta ser un programa normal del host y no un contenedor, lsof -i :8080 lo encuentra. Cambiar solo el lado del host, como -p 8081:80, te desbloquea, pero dejar el contenedor viejo ahí significa la misma colisión la próxima vez.Conflict. The container name "/api" is already in use by containerEl nombre que pasaste con --name ya lo tiene otro contenedor. Los nombres son únicos también entre los contenedores parados, no solo los que están en marcha, así que normalmente uno que murió ayer sigue reteniéndolo: no aparece en docker ps y sí en docker ps -a. docker rm -f api libera el nombre y a la vez destruye la capa de escritura de ese contenedor (los volúmenes con nombre sobreviven). Para un contenedor de un solo uso, arrancarlo con docker run --rm evita del todo la situación.failed to register layer: Error processing tar file(exit status 1): no space left on deviceNo queda espacio en el disco para descomprimir la capa de la imagen. Normalmente el proyecto no es grande: es Docker que sigue guardando meses de imágenes viejas, caché de compilación y volúmenes de contenedores que ya borraste. docker system df muestra cuánto ocupan imágenes, contenedores, volúmenes y caché de compilación y cuánto es recuperable, así que léelo antes de borrar nada. docker system prune elimina contenedores parados, imágenes colgantes, redes sin usar y la caché de compilación —la siguiente compilación será claramente más lenta sin esa caché— y añadir --volumes borra además los volúmenes no vinculados a un contenedor, que es exactamente donde la gente pierde sus bases de datos.pull access denied for myapp, repository does not exist or may require 'docker login'El registro no te mostró ese repositorio, y lo importante es que el mensaje cubre dos causas a la vez: el nombre no existe, o existe y no tienes permiso para verlo. O no has iniciado sesión para un repositorio privado, o al nombre le falta el usuario u organización (myapp y myorg/myapp son repositorios distintos), o el nombre está mal. Si la imagen es privada, haz docker login contra ese registro; si debería ser pública, revisa la ortografía. Los registros no distinguen a propósito entre "no existe" y "no puedes", porque la existencia de un nombre ya es información.manifest for myapp:v2 not found: manifest unknownEl repositorio se encontró, pero la etiqueta no está en él. A diferencia de pull access denied, este mensaje te dice que el nombre era correcto, así que solo queda revisar la etiqueta: una etiqueta borrada o movida, una tubería que subió latest pero nunca creó v2, o una etiqueta sin imagen para tu arquitectura. docker manifest inspect myapp:v2 confirma si la etiqueta se resuelve y qué plataformas incluye. Cambiar a latest para salir del paso te cuesta una compilación que no se puede reproducir, así que mejor corrige la etiqueta.unauthorized: incorrect username or passwordEl registro rechazó las credenciales que enviaste. Más a menudo que una contraseña mal escrita, esto es una contraseña enviada a un registro que ya no acepta contraseñas de cuenta: Docker Hub solo admite tokens de acceso cuando tienes doble factor, y los registros de GitHub y GitLab siempre han querido un token o una clave de despliegue. docker logout borra la credencial guardada; luego vuelve a hacer docker login con un token. Pasarlo como echo $TOKEN | docker login -u user --password-stdin mantiene el token fuera del historial del shell.failed to solve: process "/bin/sh -c npm ci" did not complete successfully: exit code: 1Esa línea RUN de tu Dockerfile terminó con un estado distinto de cero. Esta línea solo dice qué comando falló y con qué código; el motivo real está en la salida de ese comando, más arriba, que BuildKit suele plegar en cuanto un paso termina. Volver a ejecutar con docker build --progress=plain imprime la salida completa de cada paso, y si una capa en caché oculta un fallo anterior, añade --no-cache, al precio de reconstruir todo desde el primer paso. exit code: 1 no es un motivo, solo el hecho de que el comando falló.COPY failed: file not found in build context or excluded by .dockerignoreCOPY solo puede tomar archivos de dentro del contexto de compilación, y el archivo no está ahí. El contexto es el último argumento de docker build, así que normalmente apuntaste a una carpeta superior con ../x, o .dockerignore filtró el archivo: clásico cuando se ignora node_modules o *.env y luego se copia algo de dentro. El mensaje nombra ambas causas, así que lee primero cat .dockerignore y reescribe la ruta relativa a la raíz del contexto. Ampliar el contexto para arreglarlo implica enviar toda la carpeta al demonio, y cada compilación se vuelve más lenta.exec /usr/local/bin/entrypoint.sh: exec format errorEl núcleo no reconoció la cabecera de ese ejecutable y, hoy en día, casi siempre es un desajuste de arquitectura: una imagen arm64 construida en Apple Silicon ejecutándose en un host amd64, o lo contrario. Un script de shell sin su primera línea #!/bin/sh produce el mismo texto. Construir con docker build --platform=linux/amd64 es la respuesta habitual, pero no elimina el desajuste: lo tapa con emulación, y todo lo que pasa por QEMU es varias veces más lento que lo nativo. Para una imagen que vas a conservar, construir ambas arquitecturas con buildx es el camino que no cuesta nada en ejecución.standard_init_linux.go: exec user process caused: no such file or directoryEl contenedor intentó ejecutar su entrypoint y el núcleo respondió "no such file", y la trampa es que el archivo está claramente ahí. Los finales de línea del script son CRLF, así que la primera línea se lee como #!/bin/sh\r y el núcleo busca un intérprete llamado literalmente sh\r; clonar en Windows o dejar activado el autocrlf de git produce exactamente esto. dos2unix entrypoint.sh convierte ese archivo (o sed -i 's/\r$//' entrypoint.sh si no lo tienes), y una línea *.sh text eol=lf en .gitattributes evita que vuelva. Nombrar en el #! un intérprete que la imagen no tiene —bash en una imagen alpine— da el mismo texto.OCI runtime create failed: exec: "bash": executable file not found in $PATH: unknownEl contenedor se creó, pero el programa que le pediste ejecutar no estaba en el $PATH de su interior. Las imágenes basadas en Alpine traen sh y no bash, así que docker run -it myapp bash o un CMD ["bash", ...] acaban exactamente en este error, igual que cualquier herramienta que supusieras dentro de la imagen y solo exista en tu host. docker run --rm -it myapp sh te da un shell para ver qué contiene realmente la imagen. Si de verdad necesitas bash, RUN apk add --no-cache bash en el Dockerfile lo añade, al precio de una imagen más grande.

Cómo leer un mensaje de error

  • Lee desde la primera línea. Cuanto más abajo, más son las tripas de la herramienta; la causa suele estar arriba.
  • Si hay un archivo y un número de línea, empieza ahí: no el marco superior de la pila, sino la línea más alta que nombre un archivo tuyo.
  • Busca el mensaje literal, pero quita antes tus rutas y nombres de variables: eso es lo que impide que la búsqueda coincida.
  • La misma condición se redacta distinto según la versión. Si los resultados no cuadran, añade el número de versión.
  • Antes de pegar un arreglo, comprueba qué descarta. Algunos no se pueden deshacer.

Preguntas frecuentes

Q. ¿Por qué no se traducen los mensajes?

Porque los vas a buscar. La herramienta imprime en inglés y un mensaje traducido no encuentra nada. Solo el significado y la solución siguen el idioma.

Q. En mi pantalla está redactado un poco distinto.

Las herramientas cambian la redacción entre versiones. Si el esqueleto coincide tras quitar tus rutas y nombres, es el mismo error. Si la versión difiere, añádela a la búsqueda.

Q. ¿Puedo ejecutar el arreglo sin más?

Comprueba antes qué descarta. git reset --hard, un force push y docker system prune quitan cosas que no vuelven; las fichas lo indican cuando aplica.

Q. ¿Cómo busco un error que no está aquí?

Quita del mensaje tus rutas, nombres y números y busca lo que queda. Ese resto es la frase que escribieron los autores de la herramienta, y es lo que coincide.