This error occurs when the key attributes you provide in a DynamoDB operation (GetItem, UpdateItem, DeleteItem, etc.) do not match your table's defined key schema. The fix requires ensuring key names, data types, and structure align with your table definition.
The ValidationException with "The provided key element does not match the schema" means DynamoDB has rejected your request because the keys you supplied don't match the table's primary key structure. Every DynamoDB table has a key schema consisting of a partition key (required) and optionally a sort key. When you perform operations on items, you must provide keys that exactly match both the attribute names and data types defined in the table schema. This validation happens at the AWS API level before DynamoDB even attempts to retrieve or modify data. DynamoDB enforces strict key matching to ensure data integrity and prevent accidental queries against the wrong keys. Unlike some relational databases that allow flexible querying, DynamoDB requires precise key specification because keys directly determine how data is distributed and stored across partitions. The error can occur with any operation that requires key specification: GetItem, UpdateItem, DeleteItem, and Query operations on specific partition keys.
First, confirm the exact names and data types of your table's primary keys. Use the AWS Console or CLI to inspect the key schema.
# Describe table to see key schema
aws dynamodb describe-table --table-name YourTableName --region us-east-1Look for the KeySchema section in the response. It will show:
"KeySchema": [
{
"AttributeName": "userId",
"KeyType": "HASH" // This is the partition key
},
{
"AttributeName": "timestamp",
"KeyType": "RANGE" // This is the sort key (if present)
}
]Also check the AttributeDefinitions section for the data type of each key:
"AttributeDefinitions": [
{
"AttributeName": "userId",
"AttributeType": "S" // S = String, N = Number, B = Binary
},
{
"AttributeName": "timestamp",
"AttributeType": "N"
}
]Note the exact attribute names (case-sensitive) and types.
DynamoDB has two client types, and they expect different key formats. Mixing them causes validation errors.
Using DynamoDBDocumentClient (recommended for most applications):
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, GetCommand } from '@aws-sdk/lib-dynamodb';
const client = new DynamoDBClient({ region: 'us-east-1' });
const docClient = DynamoDBDocumentClient.from(client);
// Use native JavaScript types for keys
const result = await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
userId: 'user123', // String - native format
timestamp: 1640000000 // Number - native format
}
}));Using DynamoDB low-level client:
import { DynamoDBClient, GetItemCommand } from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({ region: 'us-east-1' });
// Use DynamoDB AttributeValue format for keys
const result = await client.send(new GetItemCommand({
TableName: 'YourTableName',
Key: {
userId: { S: 'user123' }, // S for String
timestamp: { N: '1640000000' } // N for Number
}
}));Using AWS CLI:
# Low-level format (must use for CLI)
aws dynamodb get-item \
--table-name YourTableName \
--key '{"userId": {"S": "user123"}, "timestamp": {"N": "1640000000"}}' \
--region us-east-1Don't mix formats—the Document Client uses native types, while the low-level client uses the DynamoDB AttributeValue format.
If your table has both a partition key and a sort key, you must provide both in GetItem, UpdateItem, and DeleteItem operations. The Query operation only requires the partition key, but Query cannot retrieve a single item with a composite key if you don't also specify the sort key.
Correct for composite key table (both keys provided):
const docClient = DynamoDBDocumentClient.from(client);
// Correct - both partition and sort key provided
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
userId: 'user123', // Partition key
timestamp: 1640000000 // Sort key
}
}));Incorrect - missing sort key:
// This will fail with "key element does not match schema"
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
userId: 'user123' // Missing timestamp sort key
}
}));For retrieving multiple items with Query (requires only partition key):
// Correct - Query with only partition key (returns multiple items)
const result = await docClient.send(new QueryCommand({
TableName: 'YourTableName',
KeyConditionExpression: 'userId = :userId',
ExpressionAttributeValues: {
':userId': 'user123'
}
}));Use Query when you need multiple items from the same partition, and GetItem when you need a single specific item.
Key attribute names must match exactly, including capitalization. DynamoDB is case-sensitive for attribute names.
// If your table schema defines:
// KeySchema: [{ AttributeName: "userId", KeyType: "HASH" }]
const docClient = DynamoDBDocumentClient.from(client);
// Correct - exact match
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
userId: 'user123' // Matches "userId" exactly
}
}));
// Incorrect - case mismatch
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
UserID: 'user123' // Will fail - doesn't match "userId"
}
}));
// Incorrect - typo
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
user_id: 'user123' // Will fail - doesn't match "userId"
}
}));Use the exact attribute names from your table schema.
The data type of each key value must match the table schema. If your partition key is defined as a Number, you cannot pass a String value.
// Table schema has:
// partition key: accountId (type: N - Number)
// sort key: timestamp (type: S - String)
const docClient = DynamoDBDocumentClient.from(client);
// Correct - correct data types
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
accountId: 12345, // Number (matches schema type N)
timestamp: '2024-01-15' // String (matches schema type S)
}
}));
// Incorrect - wrong data type for accountId
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
accountId: '12345', // String - doesn't match Number schema
timestamp: '2024-01-15'
}
}));When reading from databases or APIs, be aware that numbers might come as strings. Convert them before passing to DynamoDB:
const accountIdFromAPI = '12345'; // String from API
const docClient = DynamoDBDocumentClient.from(client);
await docClient.send(new GetCommand({
TableName: 'YourTableName',
Key: {
accountId: parseInt(accountIdFromAPI), // Convert to Number
timestamp: '2024-01-15'
}
}));When debugging, use the AWS CLI with explicit AttributeValue format to isolate whether the issue is in key specification or client-specific code.
# Test with low-level format
aws dynamodb get-item \
--table-name YourTableName \
--key '{"userId": {"S": "user123"}, "timestamp": {"N": "1640000000"}}' \
--region us-east-1
# If this succeeds, the issue is likely in your SDK client code
# If this fails, the issue is in your key specificationCompare successful CLI commands to your SDK code to identify the mismatch. The CLI uses the low-level AttributeValue format explicitly, so a working CLI command proves your keys are correct.
DynamoDB Key Format Reference: The low-level AttributeValue format uses single-letter type codes: S (String), N (Number—always a string representation), B (Binary), SS (String Set), NS (Number Set), BS (Binary Set), BOOL (Boolean), NULL, L (List), and M (Map). Keys can only be of type S, N, or B; complex types like Lists and Maps cannot be keys.
SDK Version Differences: AWS SDK v2 and v3 have different APIs and behaviors. The DocumentClient behavior changed between versions. If you migrated SDK versions and started getting this error, review the migration guide for your specific SDK version to ensure you're using the correct key format.
Terraform and Infrastructure as Code: When using Terraform with aws_dynamodb_table_item, ensure the item parameter matches the table's key schema exactly. Terraform converts HCL to JSON, which then becomes DynamoDB AttributeValue format. Mismatches here are common when the table definition and item definition get out of sync.
Nested Attributes and Key Confusion: You cannot use nested attributes (like user.id) as keys. Keys must be top-level attributes. If you have a table with a key named userId and you try to use user.userId instead, it will fail with this error. Top-level attribute names only.
Zero-Value Considerations: Empty strings ("") and zero (0) are valid key values in DynamoDB. Don't confuse a zero-valued key with a missing key—both situations require explicit handling.
Batch Operations: BatchGetItem uses the same key format as GetItem. If you're using batch operations, ensure every item in the batch has complete, correctly-formatted keys matching the table schema.
Transactions: TransactGetItems and TransactWriteItems also require correctly formatted keys. Validation happens at the transaction level, so a single malformed key can cause the entire transaction to fail.
UnrecognizedClientException: The security token included in the request is invalid
How to fix "UnrecognizedClientException: The security token included in the request is invalid" in DynamoDB
TransactionCanceledException: Transaction cancelled
How to fix "TransactionCanceledException: Transaction cancelled" in DynamoDB
RequestLimitExceeded: Throughput exceeds the current throughput limit for your account
How to fix "RequestLimitExceeded: Throughput exceeds the current throughput limit for your account" in DynamoDB
TableNotFoundException: Table not found
TableNotFoundException: Table not found in DynamoDB
InternalServerError: Internal Server Error
How to fix "InternalServerError" in DynamoDB