# Symptom
```
ValueError: Message dict must contain 'role' and 'content' keys, got {'role': 'HumanMessage', 'random_field': 'random value'}
```
## Confirm
Log the message list immediately before the model call. Find the dict the error quotes. Check its keys against the accepted shapes: message objects, `{"role": ..., "content": ...}` dicts, tuples, plain strings.
## Cause
- The dict uses the class name as the role (`"HumanMessage"` instead of `"user"`).
- A message was JSON-serialized and re-wrapped, so it is now a string containing a dict, or a dict with renamed keys.
- Custom code adds extra fields or renames `content`.
## Fix
Normalize to the OpenAI-style shape:
```python
{"role": "user", "content": "Hello world!"}
```
or construct real message objects (`HumanMessage(content=...)`). Fix the transformation where it happens (serializer, cache layer), not just at the call site.
## Verify
Re-run the invoke. If the list is built in a loop, assert the shape of every element before the call during development; the error only quotes the first offender.