AI Connect/Reference/トラブルシューティング

トラブルシューティング

VinkiusについてAIに質問

症状ごとの診断:コンストラクターエラー、AuthError、コネクタのステータス、空のケーパビリティセット、アダプタのディスパッチ失敗、タイムアウト、サポートへの診断情報。

症状から診断します。各セクションは、観測された動作をその原因と修正に対応付けます。

最初のリクエストの前にコンストラクターが例外を投げる

appId または apiKey のプレフィックスエラー。 公開 ID とシークレットキーを正しいフィールドに指定してください:

typescript
const vinkius = new Vinkius({
  appId: 'vk_app_...',
  apiKey: 'vk_app_sk_...',
});

公開 App ID は vk_app_ で始まる必要がありますが、vk_app_sk_ で始まってはいけません。キーは vk_app_sk_ で始まる必要があります。

No global fetch found. Node.js 18 以降、グローバルな fetch を持つランタイムを使用するか、コンストラクターの fetch オプションで互換性のある実装を渡してください。

Invalid externalId. vk_app_user_... 識別子ではなく、アプリケーションのユーザー ID を使用してください。1 文字から 255 文字で、空白、/、バックスラッシュを含んではいけません。

リクエストが AuthError を投げる

HTTP の 401 または 403AuthError にマッピングされます。

  1. 環境変数がサーバープロセスで読み込まれたことを確認します。
  2. Application Key が設定された App ID と環境に属していることを確認します。
  3. 失効またはローテーションされたキーを置き換えます。
  4. デプロイコードが App ID とキーを入れ替えていないか確認します。
  5. requestId があれば記録します。ただしキーは決してログに記録しないでください。

コネクターのステータスが not_connected になる

ハンドルは接続を作成しません:

typescript
const connector = vinkius.user(externalId).connector('github');
console.log(await connector.status()); // may be 'not_connected'

await connector.connect();

connect() が get-or-create リクエストを実行します。接続が存在するまで、credentials.status()credentials.set()disconnect()、コネクタースコープの capabilities()ConnectorNotConnectedError を投げます。

コネクターのステータスが needs_credentials になる

カタログのスキーマを読み、サーバー側のフローで必要な値を収集し、書き込みます:

typescript
const schema = await connector.credentials.schema();
const state = await connector.credentials.set(values);

console.log(schema, state.configured);

schema() は接続前に実行できますが、set() はできません。送信したキー名をスキーマと比較し、サービスが拒否した場合は ValidationError.errors を確認してください。保存された値は返されません。

コネクターのステータスが disabled になる

接続は存在しますが、その API ステータスはアクティブではありません。認証情報を書き直してもこの状態は変わらない場合があります。ユーザーに接続が実行できないことを示し、必要に応じて低レベルクライアント経由で接続レスポンスを確認するか、アプリケーションのフローに従って接続を置き換えてください。

user.capabilities() が空のセットを返す

空のセットは有効です。スコープとフィルターを確認します:

typescript
const user = vinkius.user(externalId);
const connectors = await user.connectors();
const capabilities = await user.capabilities({ include: ['github'] });

console.log({ connectors, count: capabilities.length });

以下を順に確認します:

  1. externalId が意図した認証済みセッションから取得されたものであること。
  2. 期待する slug が connectors() に現れること。
  3. 派生したステータスが ready であること。
  4. include がサービスが期待する正確な slug を使用していること。
  5. exclude がローカルでコネクターを除去していないこと。
  6. 集約エンドポイントが実際に接続のアクションを返したこと。

クライアントはエンドポイントのレスポンスを変換するだけで、ローカルの準備完了フィルターを追加しません。

ケイパビリティの検索が undefined を返す

両方の名前を確認します:

typescript
for (const capability of capabilities) {
  console.log(capability.name, capability.rawName, capability.connector);
}

デフォルトの表示名は github__create_issue のように名前空間付きです。findCapability() は表示名または生の名前を受け付け、最初の一致を返します。生の名前が衝突する場合は、先に forConnector(slug) を呼び出すか、名前空間付きの表示名を使用してください。

namespaceCapability を指定した場合は、その出力がプロバイダーの命名制約に合い、一意性を保っていることを確認してください。アダプターはどちらのルールも強制しません。

アダプターのディスパッチャーが Unknown capability を投げる

変換とディスパッチに同じケイパビリティ配列を渡し、返された表示名を正確に保ってください:

typescript
const tools = toOpenAITools(capabilities);
// Send tools to the model, then:
const result = await runOpenAIToolCall(capabilities, returnedCall);

OpenAI、Anthropic、Gemini のディスパッチャーは表示名のみを照合します。JSON Schema ディスパッチは表示名または生の名前を受け付け、生の名前が重複する場合は最初の一致が優先されます。不明なディスパッチ名は VinkiusError ではなく、単純な Error を投げます。

OpenAI の引数が予期せず {} になる

runOpenAIToolCallcall.function.arguments を解析します。空文字列、不正な JSON、JSON の null、プリミティブな JSON はすべて {} に変換されます。不正な引数を許容するのではなく拒否したい場合は、独自のモデルループで解析結果の形状を検証またはログに記録してください。

実行が isError: true で解決される

HTTP リクエストは完了し、ケイパビリティが失敗したアクションを報告しました。返されたコンテンツを確認します:

typescript
const result = await capability.execute(args, options);

if (result.isError) {
  console.error(result.content.map((part) => part.text).join('\n'));
}

この分岐を catch で期待しないでください。プロバイダーループは結果をモデルに返せますし、決定論的なルートはアプリケーションのエラーレスポンスにマッピングできます。文字列を返すファクトリーアダプターは isError を捨てるため、この区別が重要な場合は元のケイパビリティを直接実行してください。

実行がタイムアウトするか ConnectionError を投げる

読み取りなどの再試行可能な操作は自動的に再試行されることがあります。ケイパビリティの実行は、idempotencyKeyundefined でない場合にのみ再試行されます:

typescript
if (!operationId) throw new Error('operationId is required');

await capability.execute(args, {
  idempotencyKey: `create-issue:${operationId}`,
});

空のキーを渡さないでください。現在の実装では、ヘッダーを送らずに再試行可能と分類される可能性があります。有効なキーなしでタイムアウトした後、外部アクションが完了している可能性があります。新しい操作を送る前に照合してください。アダプターのディスパッチヘルパーはべき等キーやシグナルを渡せません。それらの制御が必要な副作用には直接実行を使用してください。

レートまたはプランのエラーが解消しない

  • RateLimitError は自動再試行の終了後に retryAfterMs を提供することがあります。
  • QuotaErrorOverageErrorupgradeUrl を提供することがあります。同じ内容を繰り返してもプランの上限は変わりません。
  • トランスポートは本文をマッピングする前に 429 を一時的と扱うため、再試行可能なリクエストは最終的なクォータエラーの前に再試行を消費することがあります。

フックにネットワーク障害が現れない

onResponse は HTTP レスポンスの後にのみ実行されます。レスポンスのないタイムアウトやネットワークエラーでは呼び出されません。onRequest は各試行の前に実行されるため、レスポンスログのないリクエストログはトランスポート障害を示す可能性があります。フックの例外は元の値のまま伝播します。フックは例外を投げないようにしてください。SDK は、シークレット風の任意のカスタムキーではなく、正確なフィールド名の固定リストをマスキングします。

サポート用の診断情報を収集する

typescript
import { VinkiusError } from '@vinkius/connect';

if (error instanceof VinkiusError) {
  console.error({
    code: error.code,
    status: error.status,
    requestId: error.requestId,
    connector: connector.slug,
    occurredAt: new Date().toISOString(),
  });
}

ローカルやトランスポートの障害では requestId が存在しないことがあります。アプリケーションキー、認証情報の値、認証ヘッダー、未確認の error.details を含めないでください。セキュリティの問題は security@vinkius.com へ非公開で報告してください。Security を参照してください。

次のステップ