Cursed Knowledge

Cursed knowledge we have learned as a result of building Immich that we wish we never knew.

  • Stabilized videos are cursed

    Video stabilization is cursed because it is implemented via crop metadata which impacts video dimensions and is sometimes automatically applied (depending on the tool), which can make dimension-based calculations wrong.

    3/25/2026

    [#27251]

  • Google's safe browsing is cursed

    Google's safe browsing service is cursed because it can flag legitimate sites as "dangerous" without any human review and continue to do so indefinitely.

    10/20/2025

    [Blog]

  • setTimeout is cursed

    The setTimeout method in JavaScript is cursed when used with small values because the implementation may or may not actually wait the specified time.

    8/4/2025

    [#20655]

  • PostgreSQL USER is cursed

    The USER keyword in PostgreSQL is cursed because you can select from it like a table, which leads to confusion if you have a table name user as well.

    8/4/2025

    [#19891]

  • PostgreSQL RESET is cursed

    PostgreSQL RESET is cursed because it is impossible to RESET a PostgreSQL extension parameter if the extension has been uninstalled.

    6/20/2025

    [#19363]

  • Zitadel Actions are cursed

    Zitadel is cursed because its custom scripting feature is executed with a JS engine that doesn't support regex named capture groups.

  • Entra is cursed

    Microsoft Entra supports PKCE, but doesn't include it in its OpenID discovery document. This leads to clients thinking PKCE isn't available.

    5/30/2025

    [#18725]

  • Image dimensions in EXIF metadata are cursed

    The dimensions in EXIF metadata can be different from the actual dimensions of the image, causing issues with cropping and resizing.

    5/5/2025

    [#17974]

  • YAML whitespace is cursed

    YAML whitespaces are often handled in unintuitive ways.

    4/1/2025

    [#17309]

  • Hidden files in Windows are cursed

    Hidden files in Windows cannot be opened with the "w" flag. That, combined with SMB option "hide dot files" leads to a lot of confusion.

    9/20/2024

    [#12812]

  • Carriage returns in bash scripts are cursed

    Git can be configured to automatically convert LF to CRLF on checkout and CRLF breaks bash scripts.

    8/7/2024

    [#11613]

  • Fetch inside Cloudflare Workers is cursed

    Fetch requests in Cloudflare Workers use http by default, even if you explicitly specify https, which can often cause redirect loops.

    8/7/2024

    [Cloudflare]

  • GPS sharing on mobile is cursed

    Some phones will silently strip GPS data from images when apps without location permission try to access them.

    7/21/2024

    [#11268]

  • PostgreSQL NOTIFY is cursed

    PostgreSQL does everything in a transaction, including NOTIFY. This means using the socket.io postgres-adapter writes to WAL every 5 seconds.

    7/3/2024

    [#10801]

  • npm scripts are cursed

    npm scripts make a http call to the npm registry each time they run, which means they are a terrible way to execute a health check.

    7/3/2024

    [#10796]

  • 50 extra packages are cursed

    There is a user in the JavaScript community who goes around adding "backwards compatibility" to projects. They do this by adding 50 extra package dependencies to your project, which are maintained by them.

    6/28/2024

    [#10690]

  • Long passwords are cursed

    The bcrypt implementation only uses the first 72 bytes of a string. Any characters after that are ignored.

    6/25/2024

  • JavaScript Date objects are cursed

    JavaScript date objects are 1 indexed for years and days, but 0 indexed for months.

    1/31/2024

    [#6787]

  • ESM imports are cursed

    Prior to Node.js v20.8 using --experimental-vm-modules in a CommonJS project that imported an ES module that imported a CommonJS modules would create a segfault and crash Node.js

    1/9/2024

    [#6719]

  • PostgreSQL parameters are cursed

    PostgresSQL has a limit of 65,535 parameters, so bulk inserts can fail with large datasets.

    12/28/2023

    [#6034]

  • Secure contexts are cursed

    Some web features like the clipboard API only work in "secure contexts" (ie. https or localhost)

    6/26/2023

    [#2981]

  • TypeORM deletes are cursed

    The remove implementation in TypeORM mutates the input, deleting the id property from the original object.

    2/23/2023

    [typeorm#6034]