Vercel環境で@ai-sdk/amazon-bedrockが「The security token included in the request is invalid」エラーになる原因と解決策

Vercel環境で@ai-sdk/amazon-bedrockが「The security token included in the request is invalid」エラーになる原因と解決策

2026.01.25

リテールアプリ共創部 マッハチームのるおんです。

Vercel AI SDKの@ai-sdk/amazon-bedrockを使ってAmazon Bedrockを呼び出す際、ローカル環境では問題なく動作するのに、Vercel環境にデプロイすると以下のエラーが発生するという問題に遭遇しました。

AI_APICallError: The security token included in the request is invalid

この問題の原因特定と解決に至るまでの過程を共有します。同じ問題で困っている方の参考になれば幸いです。

https://ai-sdk.dev/providers/ai-sdk-providers/amazon-bedrock

先に結論

原因

VercelはAWS_SESSION_TOKENなどのAWS関連環境変数を自動的に注入します。@ai-sdk/amazon-bedrocksessionTokenを明示的に渡さない場合、この環境変数を自動的に読み取ります。その結果、永続的なIAMユーザー認証情報と無関係なセッショントークンが混在 し、認証エラーが発生します。

解決策

credentialProviderを使用して認証情報を明示的に提供し、環境変数の自動読み取りをバイパスします。

createAmazonBedrock({
  region: "ap-northeast-1",
  credentialProvider: async () => ({
    accessKeyId,
    secretAccessKey,
    // sessionTokenは意図的に含めない
  }),
});

以下、原因特定に至るまでの調査過程を詳しく説明します。

問題の概要

発生状況

  • ローカル環境: 正常に動作 ✅
  • Vercel環境: 認証エラーが発生 ❌

最初の判断

ローカル環境では同じ認証情報で正常に動作しているため、以下の可能性は除外できると判断しました。

  • IAM権限不足: ローカルで動くなら権限は足りている
  • 認証情報の期限切れ: AKIAで始まる永続的なアクセスキーを使用しており、期限切れはない
  • 認証情報の誤り: ローカルで動くなら認証情報自体は正しい

つまり、Vercel環境特有の何かが原因 であると推測し、調査を進めました。

使用していた構成

  • Next.js 16.0.7
  • ai (Vercel AI SDK) v5.0.113
  • @ai-sdk/amazon-bedrock v3.0.70
  • @aws-sdk/client-s3 v3.772.0(S3は正常に動作していた)
  • IAMユーザーの永続的な認証情報(AKIAで始まるアクセスキー)

実装コード

Vercelの予約環境変数との競合を避けるため、カスタムの環境変数名(MY_AWS_*)を使用していました。

api-client.ts
createAmazonBedrock({
  region: "ap-northeast-1",
  accessKeyId,      // MY_AWS_ACCESS_KEY_IDから取得
  secretAccessKey,  // MY_AWS_SECRET_ACCESS_KEYから取得
});

原因調査の過程

1. 認証情報の確認

まず、Vercel上で認証情報が正しく渡されているかを確認するため、デバッグログを追加しました。

console.log("[DEBUG] Amazon Bedrock Client", {
  accessKeyIdExists: !!accessKeyId,
  accessKeyIdLength: accessKeyId?.length ?? 0,
  accessKeyIdPrefix: accessKeyId?.substring(0, 4) ?? "N/A",
  secretAccessKeyExists: !!secretAccessKey,
  secretAccessKeyLength: secretAccessKey?.length ?? 0,
});

結果は問題なし。AKIAで始まる20文字のアクセスキーIDと40文字のシークレットアクセスキーが正しく渡されていました。

2. CloudTrailでの確認

AWS CloudTrailでBedrockのAPIコールログを確認したところ、成功したリクエストしか記録されていませんでした。認証エラーのリクエストはCloudTrailに記録される前にAWSによって拒否されていることがわかりました。

3. 環境変数の調査

ai-sdkのソースコードを調査したところ、重要な発見がありました。

@ai-sdk/amazon-bedrock/dist/index.js
return {
  accessKeyId: loadSetting({
    settingValue: options.accessKeyId,
    environmentVariableName: "AWS_ACCESS_KEY_ID",
  }),
  secretAccessKey: loadSetting({
    settingValue: options.secretAccessKey,
    environmentVariableName: "AWS_SECRET_ACCESS_KEY",
  }),
  sessionToken: loadOptionalSetting({
    settingValue: options.sessionToken,
    environmentVariableName: "AWS_SESSION_TOKEN"  // ← ここが問題!
  })
};

sessionTokenを明示的に渡していない場合、SDKは自動的にAWS_SESSION_TOKEN環境変数を読み取ります。

4. 原因特定

Vercel上で環境変数を確認するログを追加しました。

console.log("[DEBUG] Environment check", {
  AWS_SESSION_TOKEN_exists: !!process.env.AWS_SESSION_TOKEN,
  AWS_SESSION_TOKEN_length: process.env.AWS_SESSION_TOKEN?.length ?? 0,
});

結果:

AWS_SESSION_TOKEN_exists: true
AWS_SESSION_TOKEN_length: 996

Vercelが自動的にAWS_SESSION_TOKENを注入していました!

原因の詳細

何が起きていたのか

  1. カスタム環境変数(MY_AWS_*)から永続的なIAMユーザーの認証情報を取得
  2. createAmazonBedrockaccessKeyIdsecretAccessKeyを明示的に渡す
  3. しかしsessionTokenは渡していない
  4. ai-sdkのloadOptionalSettingAWS_SESSION_TOKEN環境変数を自動的に読み取る
  5. Vercelが注入した無関係なセッショントークン(Vercelインフラ用)が使われる
  6. 永続的IAMユーザー認証情報 + 無関係なセッショントークン = 認証エラー

なぜローカルでは動いたのか

ローカル環境ではAWS_SESSION_TOKEN環境変数が設定されていなかったため、loadOptionalSettingundefinedを返し、セッショントークンなしでリクエストが送信されていました。

Vercelの公式ドキュメントの記載

VercelのReserved environment variablesには以下の記載があります。

一部のAWS関連環境変数は、明示的に設定しなくてもVercel Functionsに自動的に現れることがあります。ただし、これらはAWS権限を持たず、認証情報として使用できません。

しかし、ai-sdkはこれを知らずに自動的に読み取ってしまうのです。

解決策

credentialProviderを使用する

credentialProviderを使用することで、環境変数の自動読み取りを完全にバイパスできます。

api-client.ts
createAmazonBedrock({
  region: "ap-northeast-1",
  credentialProvider: async () => ({
    accessKeyId,
    secretAccessKey,
    // sessionTokenは意図的に含めない
  }),
});

なぜこれで解決するのか

ai-sdkのソースコードを見ると、credentialProviderが指定されている場合はloadSetting/loadOptionalSettingが呼ばれません。

@ai-sdk/amazon-bedrock/dist/index.js
if (options.credentialProvider) {
  return {
    ...await options.credentialProvider(),  // ← 環境変数を見ない
    region
  };
}
// credentialProviderがない場合のみ環境変数を読み取る

関連するGitHub Issues

この問題に関連するIssueがいくつか存在します。

Issue #3018ではbedrockOptionsを使った回避策が提案されていますが、現在のバージョン(v3.0.73)ではbedrockOptionsは認証情報用ではなく、モデルオプション用(reasoningConfiganthropicBeta等)に使われています。

まとめ

問題

Vercelが自動注入するAWS_SESSION_TOKENとai-sdkの環境変数自動読み取りが競合し、認証エラーが発生する。

解決策

credentialProviderを使用して認証情報を明示的に提供し、環境変数の自動読み取りをバイパスする。

createAmazonBedrock({
  region: "ap-northeast-1",
  credentialProvider: async () => ({
    accessKeyId,
    secretAccessKey,
  }),
});

教訓

  • ローカルと本番で環境変数が異なる可能性を常に意識する
  • SDKの内部実装(環境変数の自動読み取り等)を理解しておく
  • CloudTrailに記録されないエラーも存在する(署名検証失敗など)

おわりに

この問題は、ローカルでは動くのに本番では動かないという厄介なパターンでした。原因特定には環境変数のデバッグログが非常に有効でした。

同じ問題で困っている方の参考になれば幸いです。

参考

https://github.com/vercel/ai/issues/3018

https://github.com/vercel/ai/issues/2780

https://vercel.com/docs/environment-variables/reserved-environment-variables

https://sdk.vercel.ai/providers/ai-sdk-providers/amazon-bedrock

この記事をシェアする

FacebookHatena blogX

関連記事