What it means
DynamoDB validates a request before it does anything with it. Keys are checked against the table's schema, expressions are parsed, attribute values are type-checked, and if any of it is wrong the request is rejected without touching the table. ValidationException is that rejection.
The practical consequence is that this error is never transient. Throttling clears, conflicts resolve, capacity scales — none of that applies here. The request as constructed will be refused every time it is sent, so a retry loop around one of these does nothing except consume the function's remaining time and then fail anyway. Recognising that early saves a lot of confused debugging.
The compensating virtue is that DynamoDB's validation messages are among the most specific AWS produces. They name the missing key, the mismatched schema element, the reserved word, the invalid value. The whole diagnosis is in the sentence after the colon — which is exactly the part that gets lost when code logs error.name or catches broadly and re-raises something generic.
Two causes account for most real occurrences. The first is an absent upstream field: a path parameter, a body field, or an environment variable that is undefined, which serialises to a missing key rather than to an error at the point where it went wrong. The second is reserved words. DynamoDB reserves several hundred, and the list includes name, status, size, timestamp, data, year and value — words that are almost impossible to avoid in a real schema. Using expression attribute name placeholders by default, rather than reaching for them after being told, removes that entire category.
CloudWatch’s Errors metric: Whether CloudWatch’s Errors metric counts this depends on whether the error escaped your handler, which the log line alone does not settle. Counted only when the exception escapes the handler. This is a client-side mistake rather than a transient condition, so it fails deterministically for the affected requests. LogStitch reports the example below as caught.
What it looks like in CloudWatch
This is the shape the failure arrives in: the lines of one invocation scattered among everything else the log group received at the same moment.
CloudWatch Logs Before
7 raw lines, in the order CloudWatch delivered them.
LogStitch After
The same lines, grouped into the invocation they belong to.
Error9e13b70a-2d64-4c81-a5f0-6b8c3e2a7d19
- 16:02:55.114PLAT
START RequestId: 9e13b70a-2d64-4c81-a5f0-6b8c3e2a7d19 Version: $LATEST
- 16:02:55.118INFO
INFO Updating order status=shipped
- 16:02:55.244ERROR
ERROR ValidationException: One or more parameter values were invalid: Missing the key orderId in the item at throwDefaultError (/var/task/node_modules/@smithy/smithy-client/dist-cjs/index.js:867:20) at markShipped (/var/task/src/orders.js:112:9)3 lines - 16:02:55.402PLAT
END RequestId: 9e13b70a-2d64-4c81-a5f0-6b8c3e2a7d19
- 16:02:55.402PLAT
REPORT RequestId: 9e13b70a-2d64-4c81-a5f0-6b8c3e2a7d19 Duration: 288.11 ms Billed Duration: 289 ms Memory Size: 512 MB Max Memory Used: 99 MB Status: error
The panel on the right is generated by running the excerpt on the left through the same parser that powers the free web stitcher — it is what the tool actually produces for this input, not an illustration of it.
How to confirm it from the logs
Read past the exception name. ValidationException on its own says nothing; the sentence after the colon is the entire diagnosis, and it is unusually specific. "Missing the key" names the attribute. "The provided key element does not match the schema" means a type mismatch — a number where the table expects a string, most often. "Query condition missed key schema element" means the query has no partition key. "Attribute name is a reserved keyword" names the word.
This never appears intermittently for a fixed request shape. If some invocations succeed and others fail with the same code, the difference is in the data — a field absent on some records, or a value of an unexpected type.
Causes, most likely first
A key attribute is missing or empty
Compare the key you sent against the table's key schema. An undefined partition key serialises to nothing and produces "missing the key"; and an empty string was historically rejected outright, so old code defending against that may be sending something unexpected instead.
An attribute's type does not match the schema
Check the type of each key value against the table definition. A partition key defined as S given a JavaScript number, or a numeric id read from JSON as a string, both produce "the provided key element does not match the schema" while looking correct in the code.
A Query has no partition key condition
Read the KeyConditionExpression. Query requires an equality condition on the partition key — it cannot scan across partitions. Filtering on a non-key attribute alone means you wanted a Scan, or an index whose partition key is that attribute.
The expression uses a reserved word
Look at the attribute names in the expression. DynamoDB reserves several hundred words — name, status, size, timestamp, data among them — and using one directly in an expression is rejected. The error names the offending word.
An expression attribute value is empty, null, or the wrong shape
Check every entry in ExpressionAttributeValues for undefined and null. A value that is absent because an upstream field was missing produces a validation error at the SDK boundary rather than a null comparison.
Fixes
Use expression attribute names for anything that might be reserved
Placeholders sidestep the reserved-word list entirely, and using them by default costs nothing. status, name, size and timestamp are all reserved and all extremely common attribute names.
js// Rejected: `status` and `name` are reserved words.
// UpdateExpression: "SET status = :s, name = :n"
await client.send(new UpdateCommand({
TableName: "orders",
Key: { orderId },
UpdateExpression: "SET #status = :status, #name = :name",
ExpressionAttributeNames: { "#status": "status", "#name": "name" },
ExpressionAttributeValues: { ":status": "shipped", ":name": label }
}));
Validate the key before the call, so the error names your field
A missing key is nearly always an absent upstream field. Checking it at the boundary turns a DynamoDB validation error three frames deep into a message that says which input was missing.
jsconst orderId = event.pathParameters?.orderId;
if (typeof orderId !== "string" || orderId === "") {
return {
statusCode: 400,
body: JSON.stringify({ error: "orderId is required" })
};
}
Keep key types stable across the boundary
A numeric id that arrives as a string from JSON and is stored as a number will fail every lookup. Coerce once, at the edge, so the rest of the function cannot get it wrong.
js// Table defines orderId as N. JSON gives us a string.
const key = { orderId: Number(event.pathParameters.orderId) };
if (!Number.isInteger(key.orderId)) {
throw new Error(`orderId must be an integer, got ${event.pathParameters.orderId}`);
}
Strip undefined values rather than sending them
The document client can be told to remove undefined attributes instead of rejecting the request, which stops an optional field that happened to be absent from failing the whole write.
jsimport { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
const doc = DynamoDBDocumentClient.from(client, {
marshallOptions: {
removeUndefinedValues: true,
convertEmptyValues: false
}
});
Also seen as
The same underlying failure, worded differently by a different runtime, SDK version, or logging layer. All of these land here — there is no separate page for each phrasing.
Related errors
Errors that show up alongside this one, or that people mistake for it.
References
LogStitch finds this automatically, across every invocation in your account.
Paste a log excerpt into the free web stitcher and see it grouped, classified, and measured in your browser — nothing is uploaded. Or run the Mac app against your own AWS profiles and get the same view over every function you own.