コンテンツにスキップ

エラーハンドリング

SDK がスローするエラーはすべて UnifiedLiveError のインスタンスです。try/catch で処理します。

import {
UnifiedLiveError,
NotFoundError,
QuotaExhaustedError,
AuthenticationError,
RateLimitError,
NetworkError,
ParseError,
ValidationError,
PlatformNotFoundError,
} from "@unified-live/core";
エラー発生タイミング対処方法
NotFoundErrorコンテンツやチャンネルが存在しないID や URL を確認
QuotaExhaustedErrorYouTube の日次クォータ超過クォータがリセットされるまで待機
AuthenticationError認証情報が無効または期限切れAPI キーを確認
RateLimitErrorリトライ上限後もレート制限超過リクエスト頻度を下げる、retryAfter を確認
NetworkErrorネットワーク障害(タイムアウト、DNS、接続)接続を確認、後でリトライ
ParseErrorAPI レスポンスのパース失敗バグとして報告
ValidationError無効な入力(空の URL など)入力を修正
PlatformNotFoundErrorプラットフォームのプラグインが未登録プラグインを登録
try {
const content = await client.resolve(url);
console.log(content.title);
} catch (error) {
if (error instanceof NotFoundError) {
console.log(`${error.platform} で見つかりませんでした`);
} else if (error instanceof QuotaExhaustedError) {
console.log(`クォータ超過。リセット時刻: ${error.details.resetsAt}`);
console.log(`使用量: ${error.details.consumed}/${error.details.limit}`);
} else if (error instanceof AuthenticationError) {
console.log(`${error.platform} の認証に失敗しました`);
} else if (error instanceof NetworkError) {
console.log(`ネットワークエラー: ${error.code}`); // 例: "NETWORK_TIMEOUT"
} else if (error instanceof UnifiedLiveError) {
console.log(`SDK エラー: ${error.message} (${error.code})`);
} else {
throw error; // 予期しないエラーは再スロー
}
}

すべてのエラーには型付きの code フィールドがあり、プログラム的なハンドリングが可能です:

try {
const content = await client.resolve(url);
} catch (error) {
if (error instanceof UnifiedLiveError) {
switch (error.code) {
case "NOT_FOUND":
case "PLATFORM_NOT_FOUND":
// リソースまたはプラットフォームが見つからない
break;
case "AUTHENTICATION_INVALID":
case "AUTHENTICATION_EXPIRED":
// 認証情報の問題
break;
case "NETWORK_TIMEOUT":
case "NETWORK_CONNECTION":
case "NETWORK_DNS":
case "NETWORK_ABORT":
// ネットワーク障害
break;
case "RATE_LIMIT_EXCEEDED":
case "QUOTA_EXHAUSTED":
// レート制限
break;
case "PARSE_JSON":
case "PARSE_RESPONSE":
// レスポンスのパース失敗
break;
case "VALIDATION_INVALID_URL":
case "VALIDATION_INVALID_INPUT":
// 入力バリデーションエラー
break;
case "INTERNAL":
// 内部SDKエラー
break;
}
}
}

すべてのエラーは error.context で構造化されたメタデータを持ちます:

try {
const content = await client.resolve(url);
} catch (error) {
if (error instanceof UnifiedLiveError) {
console.log(error.platform); // "youtube"(後方互換 getter)
console.log(error.context.platform); // "youtube"
console.log(error.context.path); // "/videos"(該当する場合)
console.log(error.context.status); // 404(該当する場合)
console.log(error.cause); // 元のエラー(ラップされている場合)
}
}

RateLimitError には retryAfter プロパティがあります。リトライまでの待機秒数を示します。サーバーが値を提供しない場合は undefined です。

try {
const content = await client.resolve(url);
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`レート制限。リトライまで: ${error.retryAfter ?? "不明"}`);
}
}

SDK は以下のケースで自動的にリトライします(エラーはスローされません):

  • 429 Too Many RequestsRetry-After ヘッダーに従って待機後リトライ
  • 5xx サーバーエラー — 指数バックオフでリトライ
  • 401 Unauthorized — 認証トークンを更新してリトライ(Twitch)

すべてのリトライが失敗した場合のみエラーがスローされます。

YouTube のクォータエラーは特別です。日次クォータ(デフォルト 10,000 ユニット)を使い切ると、QuotaExhaustedError が即座にスローされます。クォータのリセットは太平洋時間の深夜なので、リトライしても意味がないためです。

try {
const streams = await client.listBroadcasts("youtube", channelId);
} catch (error) {
if (error instanceof QuotaExhaustedError) {
const { consumed, limit, resetsAt } = error.details;
console.log(`YouTube クォータ: ${consumed}/${limit}、リセット: ${resetsAt}`);
}
}