エラーの概要

AWS における 500 Internal Server Error は、クライアント側のリクエストに問題はないにもかかわらず、AWS サービス側で予期しない障害が発生したことを示します。Lambda 関数の未処理例外やタイムアウトAPI Gateway の統合エラー、CloudFormation のスタック操作失敗など、複数のサービスにまたがって発生しうるサーバーサイドの障害です。一時的な AWS 基盤の不具合である場合もありますが、大半はアプリケーションコードや設定の問題に起因します。

実際のエラーメッセージ例

API Gateway 経由での呼び出し時:

{
  "message": "Internal server error",
  "statusCode": 500
}

Lambda の CloudWatch Logs に出力されるスタックトレース:

[ERROR] Runtime.UnhandledPromiseRejection: Error: connect ETIMEDOUT 10.0.1.5:5432
Traceback (most recent call last):
  File "/var/task/handler.py", line 14, in handler
    result = db.query(sql)
TimeoutError: Connection timed out after 3000ms

CloudFormation スタック操作失敗時:

Resource handler returned message: "Internal Server Error" (RequestToken: ...,
HandlerErrorCode: InternalFailure)

よくある原因と解決手順

原因1:Lambda 関数の未処理例外

Lambda がエラーをキャッチせずに例外をスローすると、API Gateway は 500 を返します。エラーハンドリングを実装して例外を適切に処理します。

Before(エラーが発生する例):

def handler(event, context):
    data = event['body']          # KeyError の可能性
    result = process(data)        # 例外が伝播する
    return {'statusCode': 200, 'body': result}

After(修正後):

import json, logging
logger = logging.getLogger()

def handler(event, context):
    try:
        data = event.get('body', '{}')
        result = process(data)
        return {'statusCode': 200, 'body': json.dumps(result)}
    except KeyError as e:
        logger.error(f'Missing key: {e}')
        return {'statusCode': 400, 'body': json.dumps({'error': f'Bad Request: {e}'})}
    except Exception as e:
        logger.exception('Unexpected error')
        return {'statusCode': 500, 'body': json.dumps({'error': 'Internal Server Error'})}

原因2:Lambda のタイムアウト・メモリ不足

デフォルト設定タイムアウト 3 秒・メモリ 128 MB)のまま重い処理を実行すると、リソース不足で 500 が発生します。SAM テンプレートまたはコンソールから値を引き上げます。

Before(エラーが発生する例):

Resources:
  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: handler.lambda_handler
      Runtime: python3.12
      # Timeout, MemorySize を未指定(デフォルト: 3s / 128MB)

After(修正後):

Resources:
  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: handler.lambda_handler
      Runtime: python3.12
      Timeout: 30          # DB 接続・外部 API 呼び出しを含む場合は余裕を持たせる
      MemorySize: 512      # CPU も比例して増加するため処理速度も改善

原因3:API Gateway の統合タイムアウト

API Gateway のエンドポイントタイムアウトはデフォルト 29 秒(上限)です。Lambda 側の Timeout がそれ以上でも API Gateway が先に切断して 500 を返します。

Before(エラーが発生する例):

# API Gateway の統合タイムアウト設定なし(デフォルト 29,000ms)
# Lambda Timeout: 60 → API Gateway が先に切断し 500 を返す

After(修正後):

# serverless.yml (Serverless Framework)
provider:
  apiGateway:
    timeoutInMillis: 28000   # API Gateway 上限 29s より 1s 短く設定

functions:
  myFunction:
    timeout: 27              # Lambda も API Gateway より短く

ツール固有の注意点

Lambda × VPC 構成

Lambda を VPC 内に配置した場合、NAT Gateway を経由しないと外部 APIAWS サービスエンドポイントに到達できず、タイムアウトによる 500 が多発します。VPC エンドポイント(PrivateLink)を使用するか、Lambda を VPC 外に移動するのが根本対策です。

# VPC 内 Lambda から S3 への接続確認
aws lambda invoke \
  --function-name <your-function> \
  --payload '{"action":"check_s3"}' \
  response.json && cat response.json

CloudWatch Logs でのトレース

500 発生時は必ず CloudWatch Logs のロググループ(/aws/lambda/<関数名>)を確認します。Lambda のデフォルトログレベルでは print()logger.error() の出力がすべて記録されます。

# 直近のエラーログを取得
aws logs filter-log-events \
  --log-group-name "/aws/lambda/<your-function>" \
  --filter-pattern "ERROR" \
  --start-time $(date -d '1 hour ago' +%s000)

X-Ray によるボトルネック特定

AWS X-Ray を有効化すると、どのサービス呼び出しで遅延・エラーが発生しているかをトレースマップで可視化できます。Lambda 関数aws-xray-sdk を組み込むことで DB クエリや外部 HTTP 呼び出しの所要時間まで計測できます。

それでも解決しない場合

  • AWS Service Health Dashboard を確認し、対象リージョン・サービスで障害が報告されていないか確認する
  • CloudWatch Logs Insights でエラーパターンを集計し、特定のリクエストパラメータや時間帯に集中していないか分析する
  • X-Ray のサービスマップでエラー率が高いノードを特定し、依存サービスを順に切り分ける
  • AWS サポートケースを起票し、RequestId と発生時刻を添付する(Developer プラン以上で利用可能)

免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。