run-llama/llama_index · error · ValueError

Failed to serialize additional_kwargs value: {value}

Error message

Failed to serialize additional_kwargs value: {value}

What it means

When a ChatMessage is serialized (e.g. SimpleChatStore.to_dict / json persistance), each value in ChatMessage.additional_kwargs is run through _recursive_serialization and must end up as a JSON primitive/container (str, int, float, bool, dict, list, None). Objects that survive recursion unchanged -- arbitrary class instances, datetime, enums without str conversion -- trigger this ValueError.

Source

Thrown at llama-index-core/llama_index/core/storage/chat_store/simple_chat_store.py:20

import os
from typing import Any, Dict, List, Optional
from typing_extensions import Annotated

import fsspec
from llama_index.core.bridge.pydantic import Field, WrapSerializer
from llama_index.core.llms import ChatMessage
from llama_index.core.storage.chat_store.base import BaseChatStore


def chat_message_serialization(
    chat_message: Any, handler: Any, info: Any
) -> Dict[str, Any]:
    partial_result = handler(chat_message, info)

    for key, value in partial_result.get("additional_kwargs", {}).items():
        value = chat_message._recursive_serialization(value)
        if not isinstance(value, (str, int, float, bool, dict, list, type(None))):
            raise ValueError(f"Failed to serialize additional_kwargs value: {value}")
        partial_result["additional_kwargs"][key] = value

    return partial_result


AnnotatedChatMessage = Annotated[
    ChatMessage, WrapSerializer(chat_message_serialization)
]


class SimpleChatStore(BaseChatStore):
    """Simple chat store. Async methods provide same functionality as sync methods in this class."""

    store: Dict[str, List[AnnotatedChatMessage]] = Field(default_factory=dict)

    @classmethod
    def class_name(cls) -> str:
        """Get class name."""

View on GitHub (pinned to afd0fef371)

Solutions

  1. Keep additional_kwargs values JSON-native: store str/int/float/bool/dict/list only (e.g. model_dump() the object or str() an enum).
  2. Convert datetimes to ISO strings and dataclasses to dicts before attaching them to the message.
  3. If you control the object, add to-dict conversion in _recursive_serialization's supported types by using Pydantic-serializable models.
  4. Strip or transform non-serializable keys right before persistence (see validation code).

Example fix

# before
msg = ChatMessage(role='assistant', content='ok', additional_kwargs={'tool_call': tool_call_obj})
await store.set_messages('sess1', [msg])
store.persist('chat.json')  # ValueError: Failed to serialize additional_kwargs value

# after
msg = ChatMessage(role='assistant', content='ok', additional_kwargs={'tool_call': tool_call_obj.model_dump()})
await store.set_messages('sess1', [msg])
store.persist('chat.json')
Defensive patterns

Strategy: validation

Validate before calling

import json

def sanitize_additional_kwargs(msg) -> None:
    for k, v in msg.additional_kwargs.items():
        try:
            json.dumps(v)
        except (TypeError, ValueError):
            msg.additional_kwargs[k] = str(v)  # or model_dump()/isoformat()

Type guard

def kwargs_are_json_safe(msg) -> bool:
    try:
        json.dumps(msg.additional_kwargs)
        return True
    except (TypeError, ValueError):
        return False

Try / catch

try:
    store.persist(path)
except ValueError as e:
    if 'Failed to serialize additional_kwargs' in str(e):
        sanitize_additional_kwargs(msg)  # then retry persist once
    else:
        raise

Prevention

When it happens

Trigger: Storing a chat message whose additional_kwargs contains a non-JSON value, e.g. additional_kwargs={'tool_call': ToolCall(...)} or {'ts': datetime.now()}, then calling chat_store.persist() / json.dumps via the store's serializer.

Common situations: Agent frameworks attaching rich objects (tool calls, metadata dataclasses, datetimes, enums) to ChatMessage.additional_kwargs; session persistence to disk/Redis of chat histories that were only ever used in memory before.

Related errors


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/b6626d819f44ab23. Report an issue: GitHub.