AWS Lambda Error – Unable to marshal response

 

AWS Lambda Error – Unable to marshal response

By logging the raw return value, enforcing JSON-safe structures, removing non-serializable types, and ensuring a correct API Gateway response shape, you restore stable, predictable Lambda behavior.





Problem

Your Lambda completes execution, but AWS reports:

Runtime.MarshalError: Unable to marshal response

This means Lambda could not convert your handler’s return value into the required wire format.

Possible causes:

  • Handler returned a type Lambda cannot serialize (e.g., a class instance or circular reference)
  • Response is not valid JSON when using API Gateway proxy mode
  • Handler returned an unexpected structure or returned nothing at all

Clarifying the Issue

Lambda always attempts to serialize your return value into JSON (Node.js/Python) unless you explicitly write to stdout via the Runtime API. If the object cannot be serialized, or is not the format AWS expects, marshalling fails before the response ever leaves Lambda.

Key failure modes:

  • Returning non-JSON-safe objects (Date, Map, Set, Decimal, custom classes)
  • Returning Python objects that contain unserializable types
  • Returning undefined, None, or an empty return in frameworks expecting structured output

Why It Matters

An invalid response structure silently breaks API workflows and causes confusing 502/504 errors at API Gateway, ALB, or Step Functions.

Impact:

  • API Gateway will reject malformed responses with “Internal Server Error”
  • Step Functions will surface the error as a task failure with no helpful detail
  • Downstream systems receive no usable payload, triggering retries and noise

Key Terms

  • Marshalling – Converting your handler return value into JSON for transport
  • Proxy integration – API Gateway mode requiring { statusCode, headers, body }
  • Serializable type – Values that JSON.stringify/json.dumps can safely encode

Steps at a Glance

  1. Confirm the marshalling error in CloudWatch
  2. Log the raw handler return value
  3. Validate response structure
  4. Remove unserializable types
  5. Ensure API Gateway proxy mode structure is correct
  6. Add explicit JSON serialization
  7. Re-test with a controlled invocation

Detailed Steps

Step 1: Confirm the marshalling error in CloudWatch

Retrieve recent logs:

aws logs tail /aws/lambda/my-function --since 5m

You should see: Unable to marshal response.
Now determine what the handler actually returned.


Step 2: Log the raw handler return value

Add a diagnostic log inside the handler.

Node.js example:

exports.handler = async () => {
  const result = getData();
  console.log("RETURN VALUE:", result);
  return result;
};

This shows you the exact object Lambda is attempting to serialize.
Next, validate the structure.


Step 3: Validate response structure

For API Gateway proxy integrations, the return value must be:

{
  "statusCode": 200,
  "headers": { "Content-Type": "application/json" },
  "body": "{\"ok\":true}"
}

Anything else will fail marshaling or be rejected by API Gateway.
Move on to identifying bad types.


Step 4: Remove unserializable types

If your data includes Maps, Sets, Dates, Decimals, or custom classes, convert them.

Node.js example:

return {
  ok: true,
  now: new Date().toISOString(), // Date is now safely serializable
  items: Array.from(mySet),       // Set → Array
};

Python example:

return {
    "ok": True,
    "time": datetime.utcnow().isoformat(),  # datetime → string
    "items": list(my_set),                  # set → list
}

After normalizing types, enforce explicit JSON formatting.


Step 5: Ensure API Gateway proxy mode structure

If using proxy mode, the body must be a string.

Node.js:

return {
  statusCode: 200,
  body: JSON.stringify({ ok: true })
};

Python:

return {
    "statusCode": 200,
    "body": json.dumps({"ok": True})
}

Now force serialization directly.


Step 6: Add explicit JSON serialization

This ensures your response is always marshal-safe.

Node.js:

return JSON.parse(JSON.stringify(result));

Python:

return json.loads(json.dumps(result))

If this passes, your original object contained an unserializable value.

Now verify behavior end-to-end.


Step 7: Re-test with a controlled invocation

Invoke manually:

aws lambda invoke \
  --function-name my-function \
  out.json

If out.json contains valid JSON and the call succeeds, marshalling is fixed.


Pro Tips

  • Prefer primitives, dicts, lists — avoid classes in handler returns
  • Use explicit serialization in Python to catch hidden DateTime/Decimal issues
  • When using API Gateway, always stringify the body field

Conclusion

“Unable to marshal response” means your Lambda returned an object AWS could not serialize. By logging the raw return value, enforcing JSON-safe structures, removing non-serializable types, and ensuring a correct API Gateway response shape, you restore stable, predictable Lambda behavior.


Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.

Comments

Popular posts from this blog

The New ChatGPT Reason Feature: What It Is and Why You Should Use It

Insight: The Great Minimal OS Showdown—DietPi vs Raspberry Pi OS Lite

Raspberry Pi Connect vs. RealVNC: A Comprehensive Comparison