Conocimiento maldito
(immich.app)- Lista compartida de conocimiento maldito adquirida durante el desarrollo de Immich
- Se recopilan problemas inesperados encontrados en diversos entornos de software e infraestructura
- Se mencionan inconvenientes de herramientas y lenguajes como metadatos EXIF, manejo de espacios en YAML y PostgreSQL
- Algunos de estos temas se conectan directamente con seguridad, compatibilidad de plataforma y dependencias de código abierto
- Se enfoca en casos reales y causas en las que los desarrolladores deben prestar atención
Resumen
El equipo de desarrollo de Immich comparte su lista de conocimiento maldito aprendido durante el desarrollo del proyecto, algo que no quisiera volver a experimentar. Es un listado de trampas y problemas inesperados que encontró de primera mano en varias herramientas, lenguajes y plataformas durante el desarrollo y la operación de servicios reales.
Lista de conocimiento maldito
-
4 de junio de 2025
- Las Actions de Zitadel son una función maldita
- La función de scripts personalizados que ofrece Zitadel se basa en un motor JS, pero tiene una limitación porque no admite grupos de captura con nombre en expresiones regulares
-
30 de mayo de 2025
- Microsoft Entra admite PKCE, pero no lo especifica en el documento de descubrimiento de OpenID
- Esto genera un problema de no detección por parte del cliente para una función que sí existe
-
5 de mayo de 2025
- La información de tamaño en los metadatos EXIF de una imagen puede diferir del tamaño real
- Esta diferencia causa errores en operaciones de recorte y redimensionamiento
-
1 de abril de 2025
- El manejo de espacios en YAML se comporta de forma distinta a lo esperado en muchos casos
- Es sensible al formateo y existe riesgo de que el contenido se interprete de una manera distinta a la intención
-
20 de septiembre de 2024
- Los archivos ocultos de Windows no se abren con la bandera "w"
- Combinado con la opción "hide dot files" de SMB, aumenta la confusión en la navegación y procesamiento de archivos
-
7 de agosto de 2024
- En scripts Bash puede surgir un problema de retorno de carro (CRLF)
- Si Git convierte automáticamente de LF a CRLF al hacer checkout, se producen errores al ejecutar el script
-
7 de agosto de 2024
- En Cloudflare Workers,
fetchaplica HTTP por defecto aunque se indique HTTPS - Esto provoca problemas de red como bucles de redirección
- En Cloudflare Workers,
-
21 de julio de 2024
- En móviles, el compartir GPS elimina silenciosamente la información GPS de las imágenes cuando la app no tiene permisos de ubicación
- Esto afecta la precisión y la privacidad de los servicios basados en ubicación
-
3 de julio de 2024
- NOTIFY de PostgreSQL solo funciona dentro de una transacción
- Al usarlo junto con el adaptador postgres de socket.io, se generan escrituras de WAL cada 5 segundos, lo que causa carga
-
3 de julio de 2024
- Al ejecutar scripts de
npm, se envía una solicitud HTTP al registro denpmcada vez - Por eso, hacer health checks con scripts es ineficiente
- Al ejecutar scripts de
-
28 de junio de 2024
- Unos pocos usuarios de la comunidad JavaScript agregaron de forma forzada más de 50 dependencias de paquetes con el argumento de la compatibilidad hacia atrás
- Todos esos paquetes los administra la misma persona
-
25 de junio de 2024
- La implementación de bcrypt solo usa los primeros 72 bytes de una cadena
- Las letras restantes se ignoran, por lo que una contraseña larga se vuelve inútil
-
31 de enero de 2024
- El objeto Date de JavaScript indexa el año y el día desde 1, pero el mes desde 0
- Es una estructura fácil de confundir
-
9 de enero de 2024
- En Node.js antes de la versión 20.8, en proyectos CommonJS que usan la opción
--experimental-vm-modules, cuando un módulo ES vuelve a cargar un módulo CommonJS- Ocurría un problema de segfault (fallo de segmentación) que hacía que Node.js se cerrara inesperadamente
- En Node.js antes de la versión 20.8, en proyectos CommonJS que usan la opción
-
28 de diciembre de 2023
- El límite de parámetros de PostgreSQL es de 65.535
- Esto impone un límite de rendimiento en inserciones masivas de grandes conjuntos de datos
-
26 de junio de 2023
- Existen Web APIs que solo pueden usarse en Secure Contexts
- Un ejemplo es la API de portapapeles, que solo funciona en entornos HTTPS o localhost
-
23 de febrero de 2023
- La implementación de
removede TypeORM afecta directamente al valor de entrada - Incluso elimina la propiedad
iddel objeto original
- La implementación de
Conclusión
Este tipo de conocimiento maldito son trampas que se encuentran con frecuencia en entornos reales de desarrollo y operación de servicios. Si los desarrolladores identifican de antemano las restricciones y los problemas ocultos por herramienta, lenguaje y entorno, ayuda a una resolución de problemas más eficiente y al desarrollo de servicios más estables.
1 comentarios
Comentarios de Hacker News
Me encantó desde que lo vi por primera vez. Y me encantó aún más después de revisar el commit de ejemplo (aquí). En especial, me gusta que se documente el ‘conocimiento maldito’ junto con el código que resuelve el problema. La primera idea que tuve fue que esta práctica hace falta en todos los proyectos. El log no es solo catarsis, sino que convierte problemas dolorosos en experiencias de aprendizaje positivas. Publicarlo fuera también permite empatizar con quienes pasaron por lo mismo y puede convertirse en una herramienta para prevenirlo en el futuro.
Al leer lo de que ‘PostgreSQL no puede enlazar 65 mil placeholders en una sola consulta’, me sorprendió. Desde el inicio, esa idea no es particularmente buena, así que tampoco es fácil culpar a PostgreSQL. Vi en los comentarios del issue que se hizo un refactor en el ORM para separar una consulta grande en varias más pequeñas, una aproximación razonable. Personalmente, siento que unas 3,000 a 5,000 filas por consulta se ven bien. Alguien sugirió un enfoque de cargar primero los datos en una tabla TEMP y luego hacer join después, especialmente con COPY … FROM, que en rendimiento puede ser mejor, pero el cambio de código era demasiado grande y esa estrategia se terminó descartando. En general, creo que es una colección muy útil de experiencias; funciona muy bien como ejemplos de advertencia.
También me parece que la idea en sí es ‘una idea maldita’. Al leer la lista completa, el ‘catálogo de lo maldito’ se siente más como lecciones aprendidas a golpes por desarrolladores reales que como un callejón sin salida o una trampa de diseño. Claro que la calidad de cada entrada varía y hay cosas que siguen en progreso, pero lo veo con más valor cuando se entiende como un log personal de experiencia en ingeniería.
Da una sensación parecida a querer procesar todos los nombres de archivos de un sistema de archivos con xargs en una sola pasada, sin NUL. Puede fallar si hay nombres raros o rotos, o si no hay suficiente memoria. Conviene usar herramientas tipo find -print0 y parallel -0/xargs -0. Y con sed, grep, etc., hay que tener cuidado si no usas LC_ALL=C: dan errores en secuencias de caracteres multibyte.
Yo mismo ya vi el error de upsert masivo con ORM cuando fallan 65 mil bindings. Especialmente si la tabla tiene una columna de tipo array en SQL, hay que bindear por cada ítem insertado y el número de variables fluctúa. Por eso, aunque en dos ejecuciones parezca igual el número de filas y columnas, la cantidad de variables a vincular cambia en una situación inestable.
También está la estrategia de pasar los valores como argumentos de array (text[], int[], etc.). PostgreSQL lo maneja bien. ANY() es un poco más lento que IN(), pero puedes meter varios IDs en un solo parámetro. Igual, capaz el ORM no lo soportaba.
A eso también le di bola. De hecho, bindear tantos parámetros es definitivamente una práctica maldita. Si hay procesamiento masivo, en la mayoría de los casos debe usarse COPY. Agrego otro caso maldito de Postgres: el nombre de un prepared statement se recorta silenciosamente a NAMEDATALEN-1 (NAMEDATALEN es 64). Esto viene desde 2001, y de hecho ya estaba antes. Los ORM deberían ser conscientes de eso. Es raro que una persona use un nombre de prepare de más de 60 caracteres, pero en ORMs es una excepción.
El ítem de ‘instalar 50 paquetes adicionales’ fue realmente impactante. Ese autor seguramente infló muchísimo las descargas de ese paquete. Pensando en el ancho de banda y espacio en disco desperdiciados globalmente, es realmente una lástima. Me pregunto si no será para ganar fama.
El mantenedor de los paquetes señalados en este ‘conocimiento maldito’ es miembro de TC39. Es una persona que suele generar controversia en proyectos JavaScript conocidos. Hubo reclamos de que había un motivo económico en un issue específico de polyfills, pero como los ingresos de GitHub Sponsors o Tidelift no son tan altos, creo que quizá realmente se guía por una convicción de compatibilidad. En 2025 eso ya me lo pienso distinto. Está haciendo mantenimiento importante de forma constante y, dentro de la comunidad, también cumple ese rol de ir empujando ideas discutibles, algo quizá necesario.
Puede ser por fama o por una personalidad particular, pero también existe una interpretación extrema: que sea una preparación para un ataque gigantesco a la cadena de suministro de software.
Ese autor casi con toda certeza es ljharb.
Los NTFS Alternate Data Streams (ADS) de Windows permiten esconder archivos ilimitados dentro de archivos existentes. macOS, por defecto, genera en todos los volúmenes extraíbles una cantidad enorme de archivos ocultos y temporales gracias a data fork, xattr y el indexado Spotlight (md). Solución: mdutil -X /Volumes/path/to/vol
Y hay mucha telemetría opt-out en todos lados (go, yarn, meilisearch, homebrew, vcpkg, dotnet, Windows, VS Code, Claude Code, macOS, Docker, Splunk, OpenShift, Firefox, Chrome, flutter, entre otros, hay bastantes preocupaciones de privacidad).
Telemetría opt-out: en go, por defecto los datos de telemetría se guardan solo localmente. Solo con aprobación del usuario se pueden subir algunos datos a telemetry.go.dev. La carga se controla con “go telemetry on” y desactivar por completo con “go telemetry off” (ver documentación).
La telemetría que solo se puede optar por salir de ella (opt-out) es la telemetría realmente útil.
Respecto al reporte de que ‘cada vez que ejecutas un script de npm se manda una petición HTTP al registry de npm’, me cuestiono si es real. Si fuera así, sería una conducta absurda para un gestor de paquetes.
Quizá sea el paso de verificar si hay actualización.
Probablemente sea por la comprobación de actualizaciones, de ahí que a veces aparezca un banner de update.
Me parece que falta una cosa. La parte de fecha/hora en metadatos EXIF es una discusión bastante vieja. Issue de referencia 1, Issue de referencia 2, Issue de referencia 3
Se me viene a la mente ‘Madness beyond the gates’ de Hadoop y Kerberos (link). Gracias a este texto, me salvé varias veces de estar a punto de perder la cabeza. Me gustaría expresar mi agradecimiento al autor, Steve. Ni me imagino lo difícil que fue sacar ese conocimiento maldito.
La idea de reunir este tipo de conocimiento maldito en un solo lugar es muy buena. También estoy de acuerdo en que estas son fallas que solo se viven al meterse de lleno en un proyecto. De ahora en adelante voy a pensar en hacer una lista así para cada proyecto.
Este punto no es algo “maldito”, sino un asunto de seguridad y privacidad relacionado con la gestión de permisos en sistemas operativos móviles.
¡Buena idea! Me pregunto si a más personas también les gustaría compartir su propio conocimiento maldito. En mi experiencia, los nombres de archivo en MacOS también son una maldición:
En 1995, en la beta de Windows 95 hice el primer CDDB. Distribuíamos los nombres de tracks de álbumes en un archivo .ini y el proyecto se detuvo porque ese archivo tenía un límite de 64KB.
Sí. Si creas un volumen case-sensitive en sistema o volumen de datos con APFS o HFS+, te vas a meter en problemas.
El punto ‘1’ es solo la configuración por defecto. Tanto HFS como APFS tienen opción case-sensitive. NTFS también funciona parecido. Estos sistemas son case-retentive, así que se puede hacer esto:
El problema real es que Steam rechaza la instalación en sistemas case-sensitive (también en la versión de Linux).