AWS Can not deserialize instance of java.lang.String out of START_OBJECT
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The error Cannot deserialize instance of java.lang.String out of START_OBJECT means your Java code expects a plain string, but the JSON payload actually contains an object at that location. This shows up often in AWS Lambda handlers, API integrations, and SDK-based services because JSON contracts move across many layers and it is easy for the Java model to drift away from the real payload shape.
What the error is telling you
JSON has different token types. A string looks like "hello", while an object begins with { and contains named fields. If Jackson is asked to fill a Java field of type String and the incoming token is an object start, deserialization stops with this error.
A minimal broken example looks like this:
The Java model says metadata is a string, but the JSON sends an object. Jackson cannot invent a sensible conversion, so it fails.
Fix the model so it matches the payload
When the JSON is correct, the fix is to change the Java field type.
This is the cleanest solution because it preserves the actual structure of the data instead of flattening everything into strings.
AWS-specific places this appears
In AWS, this error often appears in a few recurring situations:
- A Lambda handler expects a plain field, but API Gateway or EventBridge sends a nested object.
- An SNS or SQS message body contains JSON as a string, and the code treats it as already-parsed nested fields.
- A request model was copied from an older version of the payload and no longer matches the live schema.
For example, API Gateway proxy events often put the HTTP body inside a string field named body. That means the outer event deserializes first, then you parse body separately if it contains nested JSON. Trying to map the entire event directly into your business model is a common source of confusion.
Debugging the mismatch quickly
The fastest way to debug this class of error is to log the raw payload and compare it directly with your Java class. Do not trust memory or old documentation. Look at the exact JSON your function received.
If the payload is nested but your model uses String, int, or some other scalar type, the mismatch is obvious. If the payload wraps data in an envelope such as detail, body, or Message, you may need one more Java class level than you expected.
If you truly want the raw nested object as text, you can deserialize into JsonNode or Map and convert later, but that should be a deliberate choice rather than a workaround for a wrong model.
Common Pitfalls
One common mistake is double-encoding JSON. A system may send a JSON string that itself contains JSON text. In that case, one stage expects a string and another stage expects an object. Be clear about which layer you are parsing.
Another problem is assuming that AWS service wrappers match your domain model directly. Event payloads usually include metadata, envelopes, and service-specific field names before you reach the part you care about.
Developers also forget to update model classes when the producer changes the contract. Adding one nested object field on the producer side is enough to trigger this error on the consumer side.
Finally, avoid papering over the issue by converting everything to String. That throws away type safety and usually makes the next bug harder to diagnose.
Summary
- The error means Java expected a
Stringbut the JSON token was an object. - Fix the Java field type so it matches the actual payload shape.
- In AWS systems, check for wrapper objects such as
body,detail, orMessage. - Log the raw event before changing code so you can compare model and payload directly.
- Use structured classes,
JsonNode, orMapdeliberately rather than flattening nested JSON into strings.

