DynamoDB ValidationException occurs when your request contains invalid parameter values, such as empty strings, type mismatches, missing required keys, or incorrect attribute definitions. This validation happens before the operation executes.
The ValidationException error in DynamoDB indicates that the parameters you provided in your request don't meet DynamoDB's validation requirements. This is a client-side validation error (HTTP 400) that prevents the operation from reaching the database. Common validation issues include: 1. **Empty string values**: DynamoDB does not allow empty strings in attribute values (even for non-key attributes in some SDKs) 2. **Type mismatches**: The data type of an attribute doesn't match the expected type defined in the table schema 3. **Missing required keys**: The partition key or sort key is missing from the item being inserted or queried 4. **Invalid expressions**: UpdateExpression, ConditionExpression, or KeyConditionExpression syntax is incorrect 5. **Unused AttributeDefinitions**: Table schema has attribute definitions that aren't used as keys 6. **Size violations**: Items or attributes exceed DynamoDB size limits 7. **Invalid numeric values**: Numbers passed as integers instead of strings in the low-level API
The ValidationException message usually includes specific details about what failed. Common specific errors:
ValidationException: One or more parameter values were invalid: An AttributeValue may not contain an empty string
ValidationException: One or more parameter values were invalid: Type mismatch for key userId expected: S actual: M
ValidationException: One or more parameter values were invalid: Missing the key userId in the item
ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema typeRead the full error message carefully - it tells you exactly what validation failed. This is your first diagnostic clue.
If the error mentions "empty string", remove or replace empty values:
// ❌ WRONG - This will cause ValidationException
const item = {
userId: { S: '123' },
email: { S: '' }, // Empty string not allowed
};
// ✅ CORRECT - Option 1: Remove the empty attribute
const item = {
userId: { S: '123' },
// email omitted if empty
};
// ✅ CORRECT - Option 2: Use null/NULL for missing data
const item = {
userId: { S: '123' },
email: { NULL: true },
};
// ✅ CORRECT - Option 3: With DocumentClient, enable convertEmptyValues
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
const client = new DynamoDBClient({ region: 'us-east-1' });
const docClient = DynamoDBDocumentClient.from(client, {
marshallOptions: {
convertEmptyValues: true, // Converts empty strings to NULL
removeUndefinedValues: true, // Removes undefined fields
}
});
const item = {
userId: '123',
email: '', // Will be converted to NULL
};
await docClient.send(new PutCommand({
TableName: 'Users',
Item: item
}));Best practice: Always clean your data before sending to DynamoDB. Use DocumentClient with proper marshalling options.
If the error mentions type mismatch, ensure attribute types match your table schema:
// ❌ WRONG - Type mismatch error
// Schema defines userId as String (S), but you're sending a Map (M)
const item = {
userId: { M: { value: { S: '123' } } }, // Wrong!
};
// ✅ CORRECT - Use the right type
const item = {
userId: { S: '123' }, // String type
};
// For numeric attributes, use Number string format
const item2 = {
age: { N: '25' }, // Must be string representation of number
};
// With DocumentClient (easier)
const docClient = DynamoDBDocumentClient.from(client);
const item3 = {
userId: '123', // String
age: 25, // Number (automatically converted to N)
isActive: true, // Boolean (automatically converted to BOOL)
tags: ['tag1', 'tag2'], // List (automatically converted to L)
metadata: { key: 'value' }, // Map (automatically converted to M)
};
await docClient.send(new PutCommand({
TableName: 'Users',
Item: item3
}));Key points:
- Verify your table schema for each attribute type
- With low-level API: numbers must be strings (e.g., { N: "25" } not { N: 25 })
- Use DocumentClient for automatic type marshalling
If error mentions missing key, verify partition key and sort key are included:
// ❌ WRONG - Missing partition key
const item = {
email: { S: '[email protected]' },
// userId missing! This is the partition key
};
// ✅ CORRECT - Include all required keys
const item = {
userId: { S: '123' }, // Partition key required
sortKey: { S: 'user#profile' }, // Sort key required if table has one
email: { S: '[email protected]' },
};
// Check your table schema to identify required keys
const table = await dynamodb.describeTable({
TableName: 'Users'
});
console.log('Keys:', table.Table.KeySchema);
// Output example: [
// { AttributeName: 'userId', KeyType: 'HASH' }, // Partition key
// { AttributeName: 'sortKey', KeyType: 'RANGE' } // Sort key (if present)
// ]
// For Put operations, always include all keys
await docClient.send(new PutCommand({
TableName: 'Users',
Item: {
userId: '123', // Partition key - REQUIRED
sortKey: 'profile', // Sort key - REQUIRED if defined in schema
email: '[email protected]'
}
}));
// For Query operations, partition key is required in Key
await docClient.send(new QueryCommand({
TableName: 'Users',
KeyConditionExpression: 'userId = :userId', // Partition key required
ExpressionAttributeValues: {
':userId': '123'
}
}));Critical: All keys defined in KeySchema must be present in every operation.
If error mentions condition or expression parameter, verify syntax:
// ❌ WRONG - Invalid UpdateExpression syntax
await docClient.send(new UpdateCommand({
TableName: 'Users',
Key: { userId: '123' },
UpdateExpression: 'SET email [email protected]', // Wrong syntax
}));
// ✅ CORRECT - Use proper UpdateExpression syntax
await docClient.send(new UpdateCommand({
TableName: 'Users',
Key: { userId: '123' },
UpdateExpression: 'SET email = :email',
ExpressionAttributeValues: {
':email': '[email protected]'
}
}));
// ❌ WRONG - Type mismatch in ConditionExpression
await docClient.send(new UpdateCommand({
TableName: 'Users',
Key: { userId: '123' },
ConditionExpression: 'attribute_exists(userId) AND age > "25"', // age is number, comparing with string
UpdateExpression: 'SET email = :email',
ExpressionAttributeValues: {
':email': '[email protected]'
}
}));
// ✅ CORRECT - Proper type comparison
await docClient.send(new UpdateCommand({
TableName: 'Users',
Key: { userId: '123' },
ConditionExpression: 'attribute_exists(userId) AND age > :minAge',
ExpressionAttributeValues: {
':minAge': 25, // Same type as age attribute
':email': '[email protected]'
},
UpdateExpression: 'SET email = :email'
}));
// Common expression rules:
// 1. Use placeholders for values: :value or #name
// 2. Attribute names: Use ExpressionAttributeNames if name is reserved
// 3. Values: Use ExpressionAttributeValues for all dynamic values
// 4. Type consistency: Ensure compared values have matching typesExpression best practices:
- Always use ExpressionAttributeValues for dynamic data
- Use ExpressionAttributeNames for reserved words or special characters
- Ensure value types match attribute types in schema
Check that your table schema is correctly configured:
# View complete table schema
aws dynamodb describe-table --table-name Users
# Check key schema
aws dynamodb describe-table --table-name Users \
--query 'Table.{KeySchema: KeySchema, AttributeDefinitions: AttributeDefinitions}'
# Output example:
# {
# "KeySchema": [
# {"AttributeName": "userId", "KeyType": "HASH"},
# {"AttributeName": "sortKey", "KeyType": "RANGE"}
# ],
# "AttributeDefinitions": [
# {"AttributeName": "userId", "AttributeType": "S"},
# {"AttributeName": "sortKey", "AttributeType": "S"}
# ]
# }// Verify in code before operations
const table = await dynamodb.describeTable({ TableName: 'Users' });
const keySchema = table.Table.KeySchema;
const attributeDefs = table.Table.AttributeDefinitions;
console.log('Required keys:', keySchema.map(k => k.AttributeName));
console.log('Attribute types:', attributeDefs.reduce((acc, attr) => {
acc[attr.AttributeName] = attr.AttributeType;
return acc;
}, {}));Key points:
- S = String, N = Number, B = Binary
- All keys must have AttributeDefinitions
- Unused AttributeDefinitions cause validation errors
## SDK-Specific Considerations
### AWS SDK v3 vs DocumentClient
- Low-level DynamoDBClient: Requires manual marshalling (S, N, M formats) but more control
- DocumentClient: Automatic marshalling/unmarshalling, easier to use, recommended for most cases
### Reserved Words
If you use DynamoDB reserved words as attribute names, use ExpressionAttributeNames:
// ❌ WRONG - "data" is reserved
UpdateExpression: 'SET data = :val'
// ✅ CORRECT
UpdateExpression: 'SET #d = :val',
ExpressionAttributeNames: {
'#d': 'data'
}### Terraform and IaC ValidationException
If using Terraform with DynamoDB:
- Ensure all attribute definitions in attribute blocks are used as keys
- Remove unused attribute blocks to avoid "some AttributeDefinitions are not used" error
- Validate with terraform validate before applying
### Batch Operations
ValidationException in batch operations:
- Each item must have all required keys
- All items must pass validation individually
- Use convertEmptyValues: true in DocumentClient batch operations
### Global Secondary Index (GSI) Considerations
- GSI can have different key schemas than the base table
- Must specify all GSI keys when writing through base table if attribute projections differ
- Type mismatches in GSI key attributes will cause validation errors
### Common Numeric Pitfalls
1. Infinity/NaN: { N: 'Infinity' } is invalid - use large numbers instead
2. Very large numbers: Precision beyond 38 decimal digits will cause errors
3. Scientific notation: Must be converted to standard decimal notation
4. Integer vs String: Low-level API requires { N: "25" }, not { N: 25 }
ValidationException: The provided key element does not match the schema
How to fix "ValidationException: The provided key element does not match the schema" in DynamoDB
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
InternalServerError: Internal Server Error
How to fix "InternalServerError" in DynamoDB