このブログは、記事を microCMS で管理し、Next.js で配信しています。2026年4月の移行から半年ほど運用するなかで、ドキュメントを読んだだけでは気づきにくい挙動に何度かつまずきました。記事の書き換えや入稿の多くは AI エージェント(Claude Code)に API 経由で任せており、筆者はその結果の確認と判断を担当しています。実際に起きたことを、起きた日付と対処法つきでまとめます。
検証環境
- OS: macOS 26.7.1 / Node.js v26.12.1
- Next.js 16.4.2(App Router)/ microcms-js-sdk 3.4.0
- 本文フィールド: microCMS のリッチエディタ V2
- 確認時期: 2026年7月〜10月
1. コードブロックの JSX が「後続ごと」消えた
一番大きな事故です。2026年7月31日、Next.js の記事(パフォーマンスチューニングの記事)に、スケルトンスクリーンのコード例を API で追加しました。コードブロックの中に <ArticleListSkeleton /> のような JSX を、エスケープせずにそのまま入れて送信しています。
保存後に記事を見ると、そのタグが消えただけでなく、記事の後半(「これからの評価軸」から「参考」まで)がまるごと無くなっていました。リッチエディタが JSX を未知の HTML タグとして解釈し、後続のブロックまで巻き込んだようです。作業前に取っておいたバックアップから復元して、事なきを得ました。
それ以降は、次の 2 つを決まりにしています。
- コードの中の
<>&は、必ず<>&にしてから送る - 広い範囲を一度に書き換えない。1 回変更するたびに GET し、主要な見出しが残っているかを確かめる
今その記事の本文を API で取得すると、コードは return <ArticleListSkeleton />; の形で保存されており、画面では正しく JSX として表示されています。
2. 保存すると <sup> が消えて意味が変わる
同じ日、ハノイの塔の記事で「円盤 n 枚のときの手数は 2 の n 乗 − 1」を 2<sup>n</sup> - 1 と書いて保存しました。リッチエディタ V2 は保存時に <sup> を落とすため、本文は「2n - 1」になっていました。エラーにならず、読むと別の式に見えるのが厄介な点です。
対処として、Unicode の上付き文字(ⁿ)で「2ⁿ - 1」と書き直しました。指数や添字は、タグではなく文字そのもので書くのが確実です。
3. サービスドメインの書き方ひとつで「記事 0 件」
SDK の serviceDomain には、xxxx.microcms.io の xxxx の部分だけを渡します。.microcms.io まで含めて書くと、SDK がさらに .microcms.io を付けた存在しないホストに接続しに行きます。実際に両方を試した結果です(サービス名は伏せています)。
serviceDomain: "(サブドメイン)" → totalCount 27
serviceDomain: "(サブドメイン).microcms.io" → Network Error. Details: fetch failedSDK 自体はエラーを投げます。ところがこのブログでは、CMS の一時的な障害でページが落ちないよう、取得に失敗したら空の一覧を返すようにしていました。
function getEmptyListResponse() {
return { contents: [], totalCount: 0, offset: 0, limit: 0 };
}この 2 つが組み合わさると、設定ミスなのに例外にならず、画面には「記事が 0 件」と出るだけになります。原因に気づきにくいため、環境変数の説明に「サブドメインのみ」と明記しました。
4. 単一選択のセレクトでも値は配列で返る
2026年8月、記事ごとの公開・非公開を切り替えるセレクトフィールド(「公開」「非公開」の単一選択)を追加しました。単一選択なので値は文字列だと思いがちですが、API では ["公開"] という配列で返ります。
そのため絞り込みは [equals] では一致せず、0 件になりました(実際に試して確認)。[contains] を使います。書き込むときも配列で送ります。
filters=public[contains]公開 // 一致する
filters=public[equals]公開 // 0 件
PATCH { "public": ["非公開"] }このフィールドを追加した直後は、既存の 26 記事すべてが未設定でした。先に絞り込みを本番に入れると全記事がサイトから消えるため、全件に「公開」を設定してから絞り込みを入れる順番にしました。
5. コンテンツ ID と slug は別物
このブログの記事 URL は /blog/[slug] です。API で作った記事はコンテンツ ID と slug を同じにしていますが、管理画面から追加した記事には 60_9ef-u5 のような自動生成の ID が付きます。slug で個別取得すると 404 になります。
GET /api/v1/blogs/pandas-large-csv-memory → 404(slug)
GET /api/v1/blogs/60_9ef-u5 → 200(コンテンツ ID)API で個別の記事を読み書きするときは、先に一覧を fields=id,slug で取得し、ID を確かめてから操作しています。
6. API で作った記事に publishedAt が付かず、サイトで 404
2026年10月24日に、新しい記事を API の PUT で作成しました。下書き指定を付けずに送ると公開状態で作られ、管理 API でも「公開済み」と記録されていました。ところが、コンテンツ API の応答には公開日時(publishedAt)が含まれていませんでした。
このブログは、予約投稿の記事を誤って出さないよう「publishedAt があり、現在時刻より前の記事」だけを表示します。そのため作成から 5 分ほど、記事ページは 404 のままでした。管理 API に記録されていた公開日時を明示的に書き込むと、コンテンツ API にもすぐ反映されました。
PATCH /api/v1/blogs/{コンテンツID}
{ "publishedAt": "2026-10-24T12:05:42.726Z" }放っておけば後から反映されたのかは、確かめていません。API で新規作成するときは、本文と一緒に publishedAt を送っておくのが確実です。
7. 囲みブロックが 2 つに分かれて保存される
「検証環境」などを囲むボックス(callout)は、リッチエディタが「見出しの部分」と「本文の部分」を別々の要素に分けて保存します。API から 1 つにまとめて書き込んでも、保存時に元の形へ戻されました。
そのまま表示すると、囲みが 2 つ並び、「MEMO」などのラベルが 2 回出ます。2026年8月に気づいた時点で、検証環境を書いた 10 記事すべてで起きていました。CMS 側では直せないため、表示する側で隣り合う同じ種類の囲みを 1 つにまとめる処理を入れて解決しました。
8. ビルドがレート制限で落ちる
このブログはビルド時に microCMS から記事を取得し、約 120 ページを一度に生成します。短時間に続けてビルドすると、429 Too many requests が返ってビルドが失敗することがありました(2026年10月にも発生)。間を置いて再実行すれば通ります。
対策として、タグやカテゴリーの記事数を数える処理は、ページごとに問い合わせず、全記事を 1 回のクエリで取得して数える作りにしています。Next.js のデータキャッシュで同じ応答が全ページに共有されるため、リクエスト数を大きく減らせます。
まとめ
振り返ると、困ったのはどれも「エラーにならない」挙動でした。タグが黙って消える、0 件になる、404 になる。だからこそ、API で書き込んだら毎回 GET して中身を確かめる、という地味な習慣がいちばん効きました。
- コードの
<>&はエスケープしてから送り、1 回ごとに GET で確認する - 指数・添字はタグではなく Unicode の文字で書く
serviceDomainはサブドメインだけ。失敗を空の一覧で握りつぶす作りの場合は特に注意する- セレクトの値は配列。絞り込みは
[contains] - 個別の操作は slug ではなくコンテンツ ID で行う
- API で新規作成するときは
publishedAtも送る
API の仕様は microCMS の公式ドキュメント(一覧取得 API/コンテンツ作成 API(PUT))と、microcms-js-sdk の GitHub にまとまっています。同じく AI エージェントと進めた作業の記録として、「Dependabot アラート39件を解消した記録」も書いています。




