- Add type and boundary checks for conv["reference"] access
- Prevent KeyError: 0 when reference list is empty or malformed
- Ensure reference is list type before indexing
- Handle cases where reference items are None or missing chunks
- Maintains backward compatibility with existing data structures
This resolves crashes in /api/v1/agents/<agent_id>/sessions endpoint
when conversation reference data is not properly structured.
### What problem does this PR solve?
This PR fixes a critical `KeyError: 0` that occurs in the
`/api/v1/agents/<agent_id>/sessions` endpoint when the system attempts
to access conversation reference data that is not properly structured.
**Background Context:**
The `list_agent_session` method in `api/apps/sdk/session.py` assumes
that `conv["reference"]` is always a properly indexed list with valid
dictionary structures. However, in real-world scenarios, this data can
be:
- Not a list type (could be None, string, or other types)
- An empty list when `chunk_num` tries to access index 0
- Contains None values or malformed dictionary structures
- Missing expected "chunks" keys in reference items
**Impact Before Fix:**
When malformed reference data is encountered, the API crashes with:
```json
{
"code": 100,
"data": null,
"message": "KeyError(0)"
}
```
**Solution:**
Added comprehensive safety checks including type validation, boundary
checking, null safety, and structure validation to ensure the API
gracefully handles all reference data formats while maintaining backward
compatibility.
### Type of change
- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
tags/v0.20.2
| @@ -589,14 +589,22 @@ def list_agent_session(tenant_id, agent_id): | |||
| if "prompt" in info: | |||
| info.pop("prompt") | |||
| conv["agent_id"] = conv.pop("dialog_id") | |||
| # Fix for session listing endpoint | |||
| if conv["reference"]: | |||
| messages = conv["messages"] | |||
| message_num = 0 | |||
| chunk_num = 0 | |||
| # Ensure reference is a list type to prevent KeyError | |||
| if not isinstance(conv["reference"], list): | |||
| conv["reference"] = [] | |||
| while message_num < len(messages): | |||
| if message_num != 0 and messages[message_num]["role"] != "user": | |||
| chunk_list = [] | |||
| if "chunks" in conv["reference"][chunk_num]: | |||
| # Add boundary and type checks to prevent KeyError | |||
| if (chunk_num < len(conv["reference"]) and | |||
| conv["reference"][chunk_num] is not None and | |||
| isinstance(conv["reference"][chunk_num], dict) and | |||
| "chunks" in conv["reference"][chunk_num]): | |||
| chunks = conv["reference"][chunk_num]["chunks"] | |||
| for chunk in chunks: | |||
| new_chunk = { | |||