AWS Lambda
DynamoDB
Python
Error Handling
Cloud Computing

Name 'Key' not defined Lambda function to access DynamoDB

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

The Python error NameError: name 'Key' is not defined appears frequently in AWS Lambda code that queries DynamoDB with boto3. The issue is usually simple: the code is building a key condition expression with Key(...) but never imported the helper class that defines it.

Why Key Needs an Import

When you use the higher-level DynamoDB resource API, methods such as query accept expression-builder objects instead of raw condition strings. Key is one of those helpers, and it comes from boto3.dynamodb.conditions.

python
1import boto3
2from boto3.dynamodb.conditions import Key
3
4dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
5table = dynamodb.Table("Orders")
6
7response = table.query(
8    KeyConditionExpression=Key("customer_id").eq("cust-100")
9)
10
11print(response["Items"])

Without the import, Python raises NameError before DynamoDB ever receives a request.

Fix the Lambda Function Directly

The usual fix is just to add the missing import and keep the query expression explicit.

python
1import json
2import boto3
3from boto3.dynamodb.conditions import Key
4
5dynamodb = boto3.resource("dynamodb")
6table = dynamodb.Table("Orders")
7
8
9def lambda_handler(event, context):
10    customer_id = event["customer_id"]
11
12    response = table.query(
13        KeyConditionExpression=Key("customer_id").eq(customer_id)
14    )
15
16    return {
17        "statusCode": 200,
18        "body": json.dumps(response["Items"]),
19    }

This is the correct pattern when you are querying by partition key, or by partition key plus sort key conditions.

Know the Difference Between query and get_item

Another source of confusion is that get_item also uses a parameter called Key, but that Key is just a dictionary field in the request, not the imported builder class.

python
1import json
2import boto3
3
4dynamodb = boto3.resource("dynamodb")
5table = dynamodb.Table("Orders")
6
7
8def lambda_handler(event, context):
9    response = table.get_item(
10        Key={
11            "customer_id": event["customer_id"],
12            "order_id": event["order_id"],
13        }
14    )
15
16    return {
17        "statusCode": 200,
18        "body": json.dumps(response.get("Item")),
19    }

So there are really two unrelated things with very similar names:

  • the imported Key helper class for condition expressions
  • the request parameter named Key in methods such as get_item

Mixing them up makes this error more common than it should be.

Key Versus Attr

If you are filtering on non-key attributes, you may need Attr instead of Key, or both together.

python
1import boto3
2from boto3.dynamodb.conditions import Key, Attr
3
4dynamodb = boto3.resource("dynamodb")
5table = dynamodb.Table("Orders")
6
7response = table.query(
8    KeyConditionExpression=Key("customer_id").eq("cust-100"),
9    FilterExpression=Attr("status").eq("PAID"),
10)
11
12print(response["Items"])

Use Key for partition and sort key conditions. Use Attr for other attributes in filter expressions.

Add Validation and Logging in Lambda

While the import fixes the specific NameError, Lambda code should also validate inputs and log failures cleanly so other DynamoDB problems are easier to diagnose.

python
1import json
2import logging
3import boto3
4from boto3.dynamodb.conditions import Key
5
6logger = logging.getLogger()
7logger.setLevel(logging.INFO)
8
9dynamodb = boto3.resource("dynamodb")
10table = dynamodb.Table("Orders")
11
12
13def lambda_handler(event, context):
14    customer_id = event.get("customer_id")
15    if not customer_id:
16        return {"statusCode": 400, "body": "customer_id is required"}
17
18    try:
19        response = table.query(
20            KeyConditionExpression=Key("customer_id").eq(customer_id)
21        )
22        return {
23            "statusCode": 200,
24            "body": json.dumps(response["Items"]),
25        }
26    except Exception:
27        logger.exception("Failed to query Orders for customer_id=%s", customer_id)
28        raise

This makes the function easier to operate once you get past the missing import problem.

Common Pitfalls

One pitfall is assuming that importing boto3 alone also imports Key. It does not. You must import the expression helpers explicitly.

Another is trying to use Key for non-key attribute filters. In those cases, Attr is usually the correct helper.

Developers also forget to ask whether query is the right operation at all. If you already know the full primary key, get_item is often simpler and does not need a key condition expression.

Summary

  • 'NameError: name 'Key' is not defined usually means the import is missing.'
  • Add from boto3.dynamodb.conditions import Key when using KeyConditionExpression.
  • Remember that the Key argument in get_item is not the same thing as the Key builder class.
  • Use Attr for non-key filters.
  • Add input validation and logging so Lambda failures are easier to debug.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.