世界を動かす技術を、日本語で。

呪われた知識

概要

Immich開発中に遭遇した「呪われた知識」をまとめた一覧。 各種ツールや仕様の予期せぬ挙動や制限事項を紹介。 開発者が避けたい落とし穴や混乱の原因を解説。 具体的な日付と事例ごとに整理。 実際の運用や実装時の注意点を示唆。

Immich開発で得た呪われた知識一覧

  • Zitadel Actionsの呪い

    • Zitadelのカスタムスクリプト機能は JSエンジン で実行されるが、 正規表現の名前付きキャプチャグループ がサポートされていない制限。
  • Entraの呪い

    • Microsoft Entraは PKCEをサポート しているが、 OpenIDディスカバリドキュメント に記載がなく、クライアントがPKCE非対応と誤認識する問題。
  • EXIFメタデータの画像サイズの呪い

    • EXIFメタデータの寸法情報 が実際の画像サイズと異なる場合があり、 トリミングやリサイズ 時に問題発生。
  • YAMLインデントの呪い

    • YAMLの空白文字 が直感的でない方法で処理されるため、予期せぬ動作やエラーの原因。
  • Windowsの隠しファイルの呪い

    • Windowsの隠しファイル は"w"フラグで開けず、さらに SMBの"hide dot files"オプション と組み合わさると混乱を招く。
  • Bashスクリプトのキャリッジリターンの呪い

    • GitのLF→CRLF変換 設定により、CRLFが含まれると bashスクリプトが正常動作しない 問題。
  • Cloudflare Workers内fetchの呪い

    • Cloudflare Workersのfetchリクエスト は明示的にhttpsを指定しても httpがデフォルト となり、リダイレクトループを引き起こす場合。
  • モバイルのGPS共有の呪い

    • 一部スマートフォンは 位置情報権限のないアプリ が画像にアクセスすると、 GPSデータをサイレントで削除 する挙動。
  • PostgreSQL NOTIFYの呪い

    • PostgreSQLは全てトランザクション内 で処理され、NOTIFYも例外でなく、 socket.io postgres-adapter 利用時は5秒ごとに WAL書き込み が発生。
  • npm scriptsの呪い

    • npmスクリプト実行時 に毎回npmレジストリへ httpリクエスト が発生し、 ヘルスチェック用途に不向き
  • 50個の追加パッケージの呪い

    • JavaScriptコミュニティ内に、 後方互換性のため にプロジェクトへ 50個の依存パッケージ を追加するユーザーが存在。
  • 長いパスワードの呪い

    • bcrypt実装最初の72バイトのみ を使用し、それ以降の文字は 無視 される仕様。
  • JavaScript Dateオブジェクトの呪い

    • 年・日が1始まり、月が0始まり という 不統一なインデックス 仕様。
  • ESMインポートの呪い

    • Node.js v20.8以前で --experimental-vm-modules を使い、 CommonJSプロジェクトからESモジュールを経由してCommonJSをimport すると セグフォルトでクラッシュ
  • PostgreSQLパラメータの呪い

    • PostgreSQLのパラメータ上限65,535 で、大量データのバルクインサート時に 失敗 する場合。
  • セキュアコンテキストの呪い

    • Webの一部機能(例: クリップボードAPI)セキュアコンテキスト(httpsまたはlocalhost) でのみ動作。
  • TypeORM削除の呪い

    • TypeORMのremove実装入力オブジェクトをミューテート し、 idプロパティが削除される 仕様。

Hackerたちの意見

「50個の追加パッケージ」ってやばいね。そのパッケージの作者は、めちゃくちゃダウンロードされてるみたい。全体的に帯域幅とディスクスペースの無駄遣いだよね。なんか、注目を集めたいだけなのかな。

たぶん注目を集めたいだけか、ただの変な人(ハンロンの剃刀)だと思うけど、特に疑い深い解釈をすると、この人は大規模なソフトウェア供給チェーン攻撃の準備をしてるんじゃないかって。

管理された後方互換性のアイデアが浮かぶね。特にインストール時にどれくらい遡るかをコントロールできたら、面白いかも。でも、ほとんどのケースではすぐにおかしなグラフ問題になるだろうけど。

作者はほぼ確実にljharbだね。

この「呪われた知識」に言及しているメンテナーはTC39のメンバーで、多くの人気JavaScriptプロジェクトで色々な問題に立ち向かってきた人だよ。JavaScriptやソフトウェア開発に関しては、想像を絶するようなひどい意見を出してることが多い。特にこのポリフィルの論争では、金銭的な動機があると主張する人もいたけど、GitHubのスポンサーやTideliftに関係してるかもしれないけど、その主張は確認してないし、これらのソースがどれだけ少ないかを考えると、彼が本当に後方互換性を信じているだけだと思う。彼の名前を口にするのは怖いな、彼と友達の影響力のあるJavaScriptの人たちの怒りを買うかもしれないから。2025年には、彼に対する意見が少し和らいだかな。彼は重要なメンテナンス作業をしてるし、コミュニティにおいて常に間違ってる人がいるのは、まあいいことかもしれないね。

一部のスマホは、位置情報の許可がないアプリが画像にアクセスしようとすると、GPSデータを静かに削除するよ。それは呪いじゃなくて、保護の魔法だね!

まさに防御の魔法だね。

何のことか全然わからないけど、見た感じでは設計通りに動いてるみたいだね。

一方で、ある特定のアプリはユーザーが写真から位置情報を削除するのを完全に拒否してるんだよね。https://support.google.com/photos/answer/6153599?hl=en&co=GE...

これ、ちょっとわかりにくいと思う。リンクされてる問題を見てみると、根本的な原因は「全ファイルアクセス」の権限に関係してるみたいで、細かい位置情報のアクセスだけじゃないみたい。位置情報アクセスがないアプリがEXIFを通じて位置をチェックできないのは素晴らしいけど、「全ファイルアクセス」がメタデータへのアクセスも制限するのには驚いたな。もしかしたらピッカーで選択したものが含まれてるのかも。https://gitlab.com/CalyxOS/platform_packages_providers_Media...

これを見た瞬間から大好きだった。例のコミットを見たら、さらに好きになったよ。呪われた知識のエントリーが、それに対処するための修正と一緒にコミットされてるんだ。最初の直感は、どのプロジェクトにも似たような仕組みが必要だってこと。ログはただのカタルシスじゃなくて、イライラする障害をポジティブな学びの経験に変えてくれる。公開することで、共感と予防の両方のツールになるんだね。

npmスクリプトは実行するたびにnpmレジストリにHTTPコールをするから、ヘルスチェックを実行するには最悪な方法だよね。これって本当?他にそのことについて話してるソースが見つからなかったんだけど。パッケージマネージャーとしてはありえない行動だよ。

  • WindowsのNTFSの代替データストリーム(ADS)は、既存のファイルの中に無限にファイルを隠すことができる - macOSのデータフォーク、xattrs、Spotlight(md)がデフォルトで全てのリムーバブルボリュームをインデックスするから、リムーバブルボリューム上のファイルにたくさんの隠しファイルやゴミが追加される。解決策:mdutil -X /Volumes/path/to/vol - オプトアウトのテレメトリがあるもの:go、yarn、meilisearch、homebrew、vcpkg、dotnet、Windows、VS Code、Claude Code、macOS、Docker、Splunk、OpenShift、Firefox、Chrome、flutter、そして他の企業の悪夢が山ほど。

オプトアウトテレメトリー: go デフォルトでは、テレメトリーデータはローカルコンピュータにのみ保存されるけど、ユーザーは承認されたテレメトリーデータの一部をhttps://telemetry.go.devにアップロードすることを選択できる。Goチームにテレメトリーデータをアップロードするには、次のコマンドを実行してね: go telemetry on テレメトリーを完全に無効にするには、ローカル収集も含めて、次のコマンドを実行: go telemetry off https://go.dev/doc/telemetry

どうやら一つ見逃してるみたい。議論はもっと前から続いてると思うけど[0,1]、この問題は何年も続いていて、主要なものみたいだね[2] 05/26/23(?) EXIFメタデータの日時は呪われてる [0] https://github.com/immich-app/immich/discussions/2581 [1] https://github.com/immich-app/immich/issues/6623 [2] https://github.com/immich-app/immich/discussions/12292

彼らのラインアイテムの一つは、65,000のPostgreSQLプレースホルダー(リンクされた投稿では「パラメータ」と呼ばれてる)を一つのクエリでバインドできないことを不満に思ってる。そもそもこれは呪われたアイデアだから、PostgreSQLを完全には責められないね。リンクされたGitHubの問題のコメントを見ると、彼らはORMをリファクタリングして、大きなクエリをいくつかの小さなクエリに分ける賢明なアプローチを採用したみたい。個人的には、書き込みクエリあたり3,000から5,000行が良い比率だと思ってる。別の人はまずデータを一時テーブルにロードしてから結合することを提案してたけど、これがさらにパフォーマンスを向上させるはずだった。特にCOPY … FROMとして書いてればね。でも、そのアイデアはアプリコードの変更が多すぎるってことで(賢明に)却下されたみたい。全体的に、これはかなり啓発的な呪われた知識の本だったね。いい警告がたくさんあったよ。よくやった!

別の戦略として、値を配列パラメータ(例えば、text[]やint[]など)として渡すのもいいよ。PGはそれを扱うのが得意だからね。ANY()を使うのはIN()よりわずかに遅いけど、たくさんのIDを含む単一のパラメータになるから。もしかしたら、彼らのORMがそれをサポートしてなかったのかも。

これも気になったんだけど、そんなに多くのパラメータをバインドするのは呪われてるね。大体の場合、COPYを使わないとダメだよ。ほんとに呪われたPostgresの話を教えると、準備されたステートメント名はNAMEDATALEN-1に静かに切り捨てられるんだ。NAMEDATALENは64だよ。これ、2001年にさかのぼる…というか、NAMEDATALENが32からサイズアップしたのがその時なんだ。切り捨ての動作自体はもっと古い。ORMが知っておくべきことだね。60文字以上のステートメント名を準備する人間はほとんどいないから。

これ、すごいね!他に呪われた知識をシェアしたい人いる?私にとっては、MacOSのファイル名が呪われてると思う。1. MacOSのファイル名は大文字小文字を区別しないから、file.txtとFILE.txtは同じ扱い 2. MacOSでNFCで保存されたファイル名はNFDに変換されることがある。

1はデフォルトではそうだけど、HFSとAPFSには大文字小文字を区別するオプションがあるよ。NTFSも君が言った通りの動作をするし、ファイルシステムが大文字小文字を保持するから、これで大丈夫だよ:$ echo yup > README.txt $ cat ReAdMe.TXT yup $ ls README.txt もしかしたら、呪われたファイルシステムの話は、クソったれなSteamが大文字小文字を区別するバージョンのファイルシステムにインストールを拒否するってことかも。SteamにはLinux版もあるのに。アホだな。

これ、面白いGitHubリポジトリになりそうだね。Awesome Xみたいな感じだけど、呪われたやつ。

JavaクラスをOracle DBに読み込んで、サーバー内でネイティブに実行できるよ。そのクラスはストアドプロシージャや関数を呼び出せるし、逆にストアドプロシージャや関数からも呼び出せる。サーバーサイドのJavaコードからストアドプロシージャや関数を呼び出せるから、Javaアプリがストアドプロシージャを呼び、そのストアドプロシージャがJavaクラスを呼び、さらにそのJavaクラスがストアドプロシージャを呼ぶ…って感じだね。そう、これがレガシーって呼ばれる理由だよ。