"Internal Server Error" when querying of DynamoDB in Lambda using Python

Question:

I am currently trying to read my dynamodb table "saved_measurements" with the partition key "Name". I’m doing this through API Gateway Lambda proxy integration, and have tested my
event['pathParameters']['name'] to be working just fine so that shouldn’t be the issue.

However, when I query my dynamodb table with my ‘Name’, the error appears.

{"message": "Internal server error"}

I have referenced many resources for querying dynamodb but nothing seems to work. I have also tried printing a example string within the response body like "yes" and it works with no issues. Only when I attempt to send my data in my response body do I meet that issue again.

What can I try to resolve this?

import json
import boto3
from boto3.dynamodb.conditions import Key, Attr

def lambda_handler(event, context):
  client = boto3.resource('dynamodb')
  table = client.Table('saved_measurements')

  data = table.query(KeyConditionExpression=Key('Name').eq(event['pathParameters']['name']))
  stuff = data.Items

  response = {
    "statusCode": 200,
    "headers": {
      "Content-Type": 'application/json',
      "Access-Control-Allow-Origin" : "*",
      "Access-Control-Allow-Headers" : "Content-Type",
      "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
    },
    "body": json.dumps(stuff),
    "isBase64Encoded": False
  }
  
  return response
Asked By: beefwhale

||

Answers:

You code needs some optimising, however i’m not certain it will resolve the issue. Let me share how I would write it:

import json
import boto3
from boto3.dynamodb.conditions import Key, Attr
client = boto3.resource('dynamodb')
table = client.Table('saved_measurements')
def lambda_handler(event, context):
    status_code=0
    stuff = ""
    try:
        data = table.query(KeyConditionExpression=Key('Name').eq(event['pathParameters']['name']))
        stuff = json.dumps(data['Items'])
        status_code = 200

    except Exception as e:
        print(e)
        stuff = e
        status_code = 400

    response = {
    "statusCode": status_code,
    "headers": {
        "Content-Type": 'application/json',
        "Access-Control-Allow-Origin" : "*",
        "Access-Control-Allow-Headers" : "Content-Type",
        "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
    },
    "body": stuff,
    "isBase64Encoded": False
    }

    return response

Some points on the code:

  1. Use try/except block anytime you are making API requests to ensure you are not returning exceptions to your downstream tasks unexpectedly
  2. I tend not to use dot notation in Python, hence I changed date.Items to data[‘Items’]. It tends to work more often than dot notation.
  3. Create you clients outside of your request handler in Lambda, this allows Lambda to reuse clients across multiple invocations which will improve your latency.
  4. Don’t return 200 for every request regardless on how it resulted, return the correct status code so your downstream processes don’t get confused.

Give those changes a go, if you don’t succeed, please share your APIGW config.

Answered By: Lee Hannigan