エラーハンドリング
例外階層
misskey_client の例外はすべて MisskeyClientException を頂点とするsealed classの階層で構成されています。
MisskeyClientException (sealed)
├── MisskeyApiException - サーバーからのエラーレスポンス
│ ├── statusCode: int - HTTPステータスコード
│ ├── errorCode: String? - Misskeyエラーコード
│ └── message: String? - エラーメッセージ
└── MisskeyNetworkException - ネットワーク到達不能・タイムアウト
└── cause: Object? - 元の例外
階層外の例外
MisskeyClientException が対象とするのは API と通信のエラーです。ドライブヘルパーなど一部のヘルパー API は、次の例外もスローする場合があります。
ArgumentError— 不正な引数(たとえば正でないconcurrencyや範囲外のpageSize)。リクエストを送信する前にスローされます。StateError— 前提条件が満たされていない場合。たとえばmainストリーミング購読が接続されていない状態でclient.drive.uploadFromUrlAndWait()を呼び出した場合です。DriveFolderAmbiguousException— 同じ階層に同名のフォルダが複数ある場合にresolvePath()とgetOrCreate()がスローします。sealed 階層には含まれないため、on MisskeyClientExceptionでは catch されません。
try {
final folder = await client.drive.folders.resolvePath(['Photos', 'Trip']);
} on DriveFolderAmbiguousException catch (e) {
print('${e.candidates.length} folders named "${e.name}"');
} on MisskeyClientException catch (e) {
print('Error: $e');
}
多数の項目を変更するバッチヘルパー(createMany()、moveBulkAll()、dissolveFolder()、deleteFolderRecursive() など)では、変更を開始した後に個々の操作が失敗しても例外はスローされず、MisskeyBatchResult(またはそれを含む結果)にエラーを伴う失敗、または理由を伴うスキップとして記録されます。移動先の確認の失敗など、変更を行う前に発生したエラーは引き続きスローされます。完了した項目を通知している最中に onProgress コールバックが例外をスローした場合は、実行中の処理が終わった後でそのエラーが再スローされ、完了した変更はロールバックされません。
基本的なcatchパターン
try {
final note = await client.notes.show(noteId: 'abc123');
} on MisskeyApiException catch (e) {
print('APIエラー: ${e.statusCode} - ${e.errorCode}');
} on MisskeyNetworkException catch (e) {
print('ネットワークエラー: ${e.cause}');
} on MisskeyClientException catch (e) {
print('クライアントエラー: $e');
}
HTTPステータス別ハンドリング
MisskeyApiException.statusCode でHTTPステータスコードを確認できます。
try {
await client.notes.create(text: 'Hello, Misskey!');
} on MisskeyApiException catch (e) {
switch (e.statusCode) {
case 401:
print('認証が必要です。トークンを確認してください。');
case 403:
print('この操作は許可されていません。');
case 404:
print('リソースが見つかりません。');
case 422:
print('リクエストの内容が不正です: ${e.message}');
default:
print('サーバーエラー: ${e.statusCode}');
}
}
レート制限リトライ
429レスポンス(レート制限)を受けた場合は、一定時間待機してリトライします。
Future<T> withRateLimitRetry<T>(Future<T> Function() fn) async {
while (true) {
try {
return await fn();
} on MisskeyApiException catch (e) {
if (e.statusCode == 429) {
// レート制限: 少し待ってリトライ
await Future.delayed(const Duration(seconds: 5));
continue;
}
rethrow;
}
}
}
// 使用例
final notes = await withRateLimitRetry(
() => client.notes.timeline(),
);
MisskeyClientConfig の maxRetries でリトライ回数を設定することもできます。