4 puntos por GN⁺ 2025-08-08 | 1 comentarios | Compartir por WhatsApp
  • 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, fetch aplica HTTP por defecto aunque se indique HTTPS
    • Esto provoca problemas de red como bucles de redirección
  • 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 de npm cada vez
    • Por eso, hacer health checks con scripts es ineficiente
  • 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
  • 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 remove de TypeORM afecta directamente al valor de entrada
    • Incluso elimina la propiedad id del objeto original

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

 
GN⁺ 2025-08-08
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.

    • Normalmente suelo escribir este tipo de información directamente en el mensaje del commit. Cuando alguien mira una línea de código y piensa: “¿Por qué lo escribieron así a la ligera? ¿No basta con hacer ___?” es muy útil que la explicación esté ahí.
  • 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

    • La fecha y la hora en sí también pueden ser malditas. Aunque algo parezca funcionar, cualquier función relacionada puede fallar en cualquier momento. Se vuelve más frágil si los valores incluyen zona horaria o horario de verano.
  • 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:

  1. Por defecto, macOS no distingue mayúsculas y minúsculas en nombres de archivo (file.txt y FILE.txt son equivalentes)
  2. Cuando MacOS guarda un nombre en NFC, a veces puede convertirse a NFD.
  • 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:

 $ echo yup > README.txt
 $ cat ReAdMe.TXT
 yup
 $ ls
 README.txt

El problema real es que Steam rechaza la instalación en sistemas case-sensitive (también en la versión de Linux).