はじめに
hkob の雑記録の第497回目(連続70日目)は、昨日に引き続きテンプレートの中身を確認していきます。次は skills の中にある sync-debug の SKILL.md を読んでみます。
sync-debug/SKILL.md
name: sync-debug description: 失敗している / 想定と違う動きをする sync を診断する — 実行ログ取得、エラー特定、コードとの突合、修正提案 user-invocable: true disable-model-invocation: true allowed-tools: ["Read", "Bash", "Glob", "Grep", "Edit", "Write"]
昨日と同じように SKILL の概要が書かれています。こちらは sync に問題があるときにどうやってデバッグするかを示した指示書です。
Instructions(手順)
sync が失敗する、または誤った結果を出す理由を特定するため、以下の手順を体系的に進める。
sync が失敗した時に以下の Step を順に試していく形になります。
Step 1: 現在状態を取得する
状況把握のため、次を実行する:
ntn workers sync status表示される sync、各 status、最終実行時刻、次回スケジュールを確認する。固まっている / 失敗している / 最近実行されていない sync を探す。
Step 1 では status で状況を確認し、失敗していたり最近実行されていない sync があるかを確認します。
Step 2: 直近の Run を取得する
ntn workers runs listexit code が 0 ではない run(テーブル表示では赤)を探す。失敗している run の run ID を控える。
list で直近の run を取得して exit code が 0 でない失敗している run を探し、その ID を取得します。
Step 3: ログを取得する
最新の run(capability 問わず):
ntn workers runs list --plain | head -n1 | cut -f1 | xargs -I{} ntn workers runs logs {}特定 sync の最新 run:
ntn workers runs list --plain | grep <syncKey> | head -n1 | cut -f1 | xargs -I{} ntn workers runs logs {}ログ全体を読む。エラーメッセージ、スタックトレース、sync コードの
console.log出力を探す。
特定の log を取得するコマンドが示されています。最新の run か特定 sync の run のどちらかで該当するコマンドを実行します。
Step 4: sync コードを読む
src/index.ts(および import されているモジュール)を読み、sync のロジックを把握する。ログのエラーと該当コードを突き合わせる。
ログのエラーと src/index.ts を照らし合わせて問題を解決します。Step 5 で診断を行います。
Step 5: 診断する
よくある失敗パターンと対処:
ここから失敗パターンが紹介されています。
API 認証エラー(401/403)
- OAuth 設定を確認:
ntn workers oauth token <oauthKey>- 環境変数を確認:
ntn workers env list- リモート側に env がない場合:
ntn workers env push- OAuth トークン期限切れの場合:
ntn workers oauth start <key>で再認証
エラーコードが 401 や 403 の場合には、API の認証エラーの可能性があります。認証エラーが発生していた場合、上記の 4 つの状況を確認します。OAuth トークンの期限切れはよくありそうですね。
レート制限(429)
- sync コードのバッチサイズを小さくする
- 必要なら API コール間に遅延を入れる
- API のレート制限仕様を確認する
エラーコードが 429 の場合には、API のレート制限に引っかかっている可能性があります。この場合、ここにあるようなレート制限の回避を検討する必要があります。
タイムアウト / 実行時間超過
- 1 回の execute が長すぎる
- バッチサイズを小さくする(ページあたりのレコード数を減らす)
- レコードごとの処理を簡略化する(重い変換を後回しにする)
エラーにタイムアウトなどがでていた場合には、ここにあるような作業の軽量化を検討する必要があります。
カーソル / state エラー
- state アクセスで TypeError: 初回実行(state が undefined)の扱い漏れの可能性
- コード更新後に state 形状が変わった: 永続化されている旧 state が残っている
- 対処:
ntn workers sync state reset <key>で state をクリアし、最初から backfill し直す
初回実行時にカーソルに関するエラーがでていた場合には、state の設定ミスが考えられます。それ以降にカーソルに関するエラーがでてしまった場合には、どこかのタイミングで state の処理に失敗したことになるので、Delta ではなく reset 後に backfill で一度やり直すとよいようです。
スキーマ不一致
changesの properties がschema.properties定義と一致していない- 各 change の
propertiesオブジェクトの key が schema の key と一致しているか確認Schema.title()にはBuilder.title()、Schema.richText()にはBuilder.richText()…のように対応しているか確認
値の書き込みに失敗している場合には、Schema で設定した型と Builder の型が一致していない場合が考えられます。これは初回 sync 時にほとんど引っかかると思いますが、稀にしか値がでてこないプロパティの場合には、その値が出たときにエラーが発生するのかもしれません。
無限ループ(sync が終わらない)
hasMoreが常にtrue(カーソルが進んでいない)- 反復ごとに
nextStateが変化しているか確認- 終了条件が到達可能か確認
sync がいつまで経っても終わらない場合には、終了条件が正しくないことが考えられます。hasMore のフラグや nextState で正しくカーソルが指示できているのか確認する必要がありそうです。
結果が空
- API がデータを返していない: API 呼び出しを直接試す(curl / local exec)
- エンドポイントやクエリパラメータが間違っている
- 認証は通るが権限/スコープが不足している
同期しているのにうまく値が入らない場合には、そもそもデータが受け取れているか確認する必要があります。直接 API を curl などで確認してみるといいでしょう。そもそも外部ツールの権限が足りないという可能性もあります。
ネットワーク / 一過性エラー
- 単発: 一時障害の可能性 — 後続 run が成功しているか確認
- 継続: API URL、DNS、接続性を確認
- リトライを強制:
ntn workers sync trigger <key>
一時的なネットワークエラーなどが原因の場合もあります。その後の run が動作しているようであれば、気にしなくてもいいかもしれません。それが何度か継続するようであれば、接続性をちゃんと確認する必要があります。強制的に trigger をかけて、リトライさせてみて原因を探ってもいいようです。
Step 6: 修正して検証する
原因を特定したら:
- コードに修正を適用する
npm run checkで型を確認する- state 形状が変わった場合、
ntn workers sync state reset <key>が必要になる可能性をユーザーへ警告する(フル再バックフィルになる)- デプロイして preview で検証する(
/sync-previewの提案、またはntn workers deploy && ntn workers sync trigger <key> --preview)- 検証できたら
ntn workers sync trigger <key>で再開する
原因がわかったらコードを修正した上で、上記の手順により preview 検証ののちに trigger で sync を再開します。
おわりに
実際に運用していくと、これ以外にもいろいろと問題が発生しそうな気がします。とりあえず、対処法がいろいろと書かれているので非常に参考になりますね。
https://hkob.notion.site/hkob-16dd8e4e98ab807cbe3cf3cc94cdfe0f?pvs=4hkob.notion.site