症状

2月で止まっていたnoteアーカイブを、note公開APIから自動同期する仕組みに切り替えて41件を一括追補した。

同期は成功、検証も通過。ところがビルドが NoMatchingStaticPathFound で停止した。

要求パスは /tags/副業/。

昨日まで通っていたビルドが、データを増やした途端に落ちる。コードは(ほぼ)触っていないのに。

検証環境

Astro 7.0.7の静的サイト。

noteの記事メタデータをアーカイブJSONに取り込み、カテゴリ別のタグページを getStaticPaths で静的生成する構成。

原因候補と確認したこと

最初に疑ったのは自分が書いた同期スクリプト。でも生成されたJSONは検証を通っている。

エラーメッセージをよく見ると、要求パスが日本語の /tags/副業/。

既存のカテゴリは全部英字スラグ(ai、podcast など)だったのに、新規記事のハッシュタグ由来で「副業」という未知カテゴリが混ざっていた。

実際の原因

カテゴリ→スラグ変換に、未知カテゴリ用のフォールバックとして encodeURIComponent(category) が仕込まれていた。

これが %E5%89%AF%E6%A5%AD のようなエンコード済みスラグを登録する一方、Astroの静的ルーティングはデコード済みの /tags/副業/ で照合する。

登録名と照合名が別表記になり、一致するページが見つからない。

登録時 副業 encodeURIComponent %E5%89%AF%E6%A5%AD 照合時 Astroルーティング /tags/副業/ ≠ NoMatchingStaticPathFound でビルド停止
図1: 同じ「副業」なのに、登録名はエンコード済み、照合名はデコード済み。別表記になって一致しない。

質が悪いのは、既知カテゴリしか存在しなかった数ヶ月間はこのコードが一度も実行されず、正常に見えていたこと。

データが増えた日に初めて爆発する、静かな地雷だった。

解決方法と解決確認

表示側でエンコード問題を頑張るのはやめて、取り込み口で正規化する方針にした。

同期スクリプトがnoteのハッシュタグをサイトの既知カテゴリ(AI/ゲーム開発/ポッドキャスト/コラム/未分類)へマッピングし、非ASCIIスラグをそもそも発生させない。

noteのハッシュタグ #副業 #AI活用 #つくってみた #ポッドキャスト 取り込み口で 正規化 既知カテゴリだけ AI ゲーム開発 ポッドキャスト コラム 未分類
図2: 検収はゲートでやる。自由なタグは取り込み口で既知カテゴリへ寄せ、非ASCIIスラグを発生させない。

再同期→ビルド成功(29ページ)→本番デプロイ後、アーカイブ一覧に73件が並んでいることを確認した。

今回得たEXP

ひとつめ。URLスラグの自動フォールバックに非ASCII文字を通さない。

エンコードの往復はどこかで必ず表記が食い違う。

ふたつめ。外部サービスの自由なタグは、取り込み口で自前の分類に正規化する。

「あとで表示側がなんとかする」は、なんとかならない。

現場でいうと、資材の受け入れ検収を省略して置き場に直行させた結果、規格外の資材が工程の奥で詰まった状態。

検収はゲートでやる。