{"record":{"id":"b6626d819f44ab23","repo":"run-llama/llama_index","slug":"failed-to-serialize-additional-kwargs-value-valu","errorCode":null,"errorMessage":"Failed to serialize additional_kwargs value: {value}","messagePattern":"Failed to serialize additional_kwargs value: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/storage/chat_store/simple_chat_store.py","lineNumber":20,"sourceCode":"import os\nfrom typing import Any, Dict, List, Optional\nfrom typing_extensions import Annotated\n\nimport fsspec\nfrom llama_index.core.bridge.pydantic import Field, WrapSerializer\nfrom llama_index.core.llms import ChatMessage\nfrom llama_index.core.storage.chat_store.base import BaseChatStore\n\n\ndef chat_message_serialization(\n    chat_message: Any, handler: Any, info: Any\n) -> Dict[str, Any]:\n    partial_result = handler(chat_message, info)\n\n    for key, value in partial_result.get(\"additional_kwargs\", {}).items():\n        value = chat_message._recursive_serialization(value)\n        if not isinstance(value, (str, int, float, bool, dict, list, type(None))):\n            raise ValueError(f\"Failed to serialize additional_kwargs value: {value}\")\n        partial_result[\"additional_kwargs\"][key] = value\n\n    return partial_result\n\n\nAnnotatedChatMessage = Annotated[\n    ChatMessage, WrapSerializer(chat_message_serialization)\n]\n\n\nclass SimpleChatStore(BaseChatStore):\n    \"\"\"Simple chat store. Async methods provide same functionality as sync methods in this class.\"\"\"\n\n    store: Dict[str, List[AnnotatedChatMessage]] = Field(default_factory=dict)\n\n    @classmethod\n    def class_name(cls) -> str:\n        \"\"\"Get class name.\"\"\"","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/storage/chat_store/simple_chat_store.py#L2-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Keep additional_kwargs values JSON-native: store str/int/float/bool/dict/list only (e.g. model_dump() the object or str() an enum).","Convert datetimes to ISO strings and dataclasses to dicts before attaching them to the message.","If you control the object, add to-dict conversion in _recursive_serialization's supported types by using Pydantic-serializable models.","Strip or transform non-serializable keys right before persistence (see validation code)."],"exampleFix":"# before\nmsg = ChatMessage(role='assistant', content='ok', additional_kwargs={'tool_call': tool_call_obj})\nawait store.set_messages('sess1', [msg])\nstore.persist('chat.json')  # ValueError: Failed to serialize additional_kwargs value\n\n# after\nmsg = ChatMessage(role='assistant', content='ok', additional_kwargs={'tool_call': tool_call_obj.model_dump()})\nawait store.set_messages('sess1', [msg])\nstore.persist('chat.json')","handlingStrategy":"validation","validationCode":"import json\n\ndef sanitize_additional_kwargs(msg) -> None:\n    for k, v in msg.additional_kwargs.items():\n        try:\n            json.dumps(v)\n        except (TypeError, ValueError):\n            msg.additional_kwargs[k] = str(v)  # or model_dump()/isoformat()","typeGuard":"def kwargs_are_json_safe(msg) -> bool:\n    try:\n        json.dumps(msg.additional_kwargs)\n        return True\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":"try:\n    store.persist(path)\nexcept ValueError as e:\n    if 'Failed to serialize additional_kwargs' in str(e):\n        sanitize_additional_kwargs(msg)  # then retry persist once\n    else:\n        raise","preventionTips":["Only attach JSON-native values (str/int/float/bool/dict/list/None) to ChatMessage.additional_kwargs.","Convert datetimes to ISO strings and Pydantic/dataclass objects via model_dump()/asdict() at attach time.","Run a json.dumps smoke test on messages before persisting a session."],"tags":["chat-store","serialization","chat-message","json","llama-index"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}