第8章 エラーハンドリングと運用のベストプラクティス
Notion API を安定して運用するためのエラーハンドリング手法、レートリミット対策(指数バックオフ)、およびセキュリティ面での注意点を解説します。
主要な HTTP ステータスコードとエラー種別
Notion API で問題が発生した場合、標準的な HTTP ステータスコードとともに、JSON 形式のエラー詳細が返されます。
| HTTP コード | Notion エラーコード | 主な原因と対策 |
|---|---|---|
400 | validation_error | リクエストの JSON 形式やプロパティの型が不正。型定義を見直す。 |
401 | unauthorized | トークンが無効または指定されていない。.env の値を確認する。 |
404 | object_not_found | 指定した ID のページ・DB が存在しない、またはインテグレーションが未接続。 |
429 | rate_limited | リクエスト頻度が高すぎる。少し待機してから再試行する。 |
500 / 502 | internal_server_error | Notion 側のサーバー障害。時間をおいて再試行する。 |
SDK によるエラーハンドリングの実装
notion-client を使用する場合、API の失敗は APIResponseError 例外として発生します。
例外をキャッチすることで、プログラムが異常終了するのを防ぎ、適切な対処を行えます。
import os
from dotenv import load_dotenv
from notion_client import Client
from notion_client.errors import APIResponseError
load_dotenv()
notion = Client(auth=os.getenv("NOTION_TOKEN"))
try:
response = notion.pages.retrieve(page_id="invalid_page_id")
except APIResponseError as error:
print(f"Notion API エラー検知!")
print(f"ステータスコード: {error.status}")
print(f"エラーコード: {error.code}")
print(f"メッセージ: {error.message}")
except Exception as e:
print(f"予期しないエラー: {e}")
レートリミット(429)と指数バックオフ
Notion API の制限目安は「1 秒あたり平均 3 リクエスト」です。
大量のデータを一度に更新・取得しようとすると、429 Rate Limited エラーが発生することがあります。
429 エラーが返された場合は、レスポンスヘッダーの Retry-After(秒数)を参照して待機するか、徐々に待機時間を延ばしながら再試行する 指数バックオフ(Exponential Backoff) を実装します。
import time
import requests
def request_with_retry(url, headers, max_retries=5):
delay = 1.0 # 初期待機時間(秒)
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
# 成功した場合はレスポンスを返す
if response.status_code == 200:
return response.json()
# レートリミットの場合は待機して再試行
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", delay))
print(f"レートリミット発生。{retry_after} 秒待機します(試行 {attempt + 1}/{max_retries})")
time.sleep(retry_after)
delay *= 2 # 待機時間を倍増
continue
# その他のエラーは中断
response.raise_for_status()
raise RuntimeError("最大再試行回数を超過しました。")
運用のセキュリティ・ベストプラクティス
- シークレットキーの分離: トークンはソースコードに直接書かず、環境変数やシークレット管理ツールで保持します。
- 接続権限の最小化: インテグレーションには必要なページやデータベースのみを接続し、ワークスペース全体への無制限なアクセスを避けます。
- ログ出力時のマスキング: トークンや個人情報(メールアドレス等)がログファイルに出力されないよう配慮します。
- 定期的な棚卸し: 使わなくなったインテグレーションや接続権限は、開発者ポータルおよびページの設定から削除します。