Skip to content

[Bug] DatabaseSessionService fails with MySQL/pymysql: TypeError 'tuple' object cannot be interpreted as an integer when serializing EventActions #3294

@procaross

Description

@procaross

Bug Description

When using DatabaseSessionService with MySQL and pymysql driver, attempting to save events fails with a serialization error:

TypeError: 'tuple' object cannot be interpreted as an integer
[SQL: INSERT INTO events (..., actions, ...) VALUES (...)]

This occurs when ADK tries to serialize EventActions objects to the actions LONGBLOB field in the database.

Steps to Reproduce

import asyncio
from google.adk.events import Event, EventActions
from google.adk.sessions import DatabaseSessionService
import time
import uuid

async def reproduce_bug():
    # Initialize DatabaseSessionService with MySQL
    db_url = "mysql+pymysql://user:password@host:3306/database"
    db_service = DatabaseSessionService(db_url=db_url)
    
    # Create a session
    session = await db_service.create_session(
        app_name="test_app",
        user_id="test_user",
        session_id=f"test_{uuid.uuid4().hex}"
    )
    
    # Try to save an event with EventActions
    event = Event(
        invocation_id=f"inv_{uuid.uuid4().hex}",
        author="system",
        actions=EventActions(state_delta={'key': 'value'}),
        timestamp=time.time()
    )
    
    # This will fail with TypeError
    await db_service.append_event(session=session, event=event)

asyncio.run(reproduce_bug())

Error Message

Traceback (most recent call last):
  File "/path/to/sqlalchemy/engine/base.py", line 1815, in _execute_context
    context = constructor(...)
  File "/path/to/sqlalchemy/engine/default.py", line 1527, in <dictcomp>
    flattened_processors[key](compiled_params[key])
  File "/path/to/sqlalchemy/sql/sqltypes.py", line 918, in process
    return DBAPIBinary(value)
  File "/path/to/pymysql/__init__.py", line 129, in Binary
    return bytes(x)
TypeError: 'tuple' object cannot be interpreted as an integer

[SQL: INSERT INTO events (id, app_name, user_id, session_id, invocation_id, author, actions, ...) VALUES (...)]

Root Cause

The issue occurs in the serialization chain:

  1. ADK uses pickle to serialize EventActions objects
  2. SQLAlchemy 2.0 processes BLOB columns and calls pymysql.Binary()
  3. pymysql's Binary() function expects bytes or an iterable of integers, but receives a complex pickled object (tuple)
  4. bytes(tuple) fails with the TypeError

Environment

  • ADK Version: 1.17.0
  • SQLAlchemy Version: 2.0.44
  • pymysql Version: 1.1.2
  • MySQL Version: 8.0
  • Python Version: 3.11.14
  • Operating System: macOS / Linux

Expected Behavior

DatabaseSessionService should correctly serialize and deserialize EventActions objects when using MySQL with pymysql driver, just as it works with other database backends.

Current Workaround

We've created a temporary patch that intercepts SQLAlchemy's parameter processing:

import pickle
from sqlalchemy import event
from sqlalchemy.engine import Engine

def _binary_value_converter(value):
    if isinstance(value, bytes):
        return value
    return pickle.dumps(value)

@event.listens_for(Engine, "before_cursor_execute", retval=True)
def _patch_binary_params(conn, cursor, statement, parameters, context, executemany):
    if isinstance(parameters, dict) and 'actions' in parameters:
        if not isinstance(parameters['actions'], bytes):
            parameters['actions'] = _binary_value_converter(parameters['actions'])
    return statement, parameters

Full patch implementation available at: [link to our patch file if you want to share]

Suggested Solution

Possible fixes:

  1. Option 1: In DatabaseSessionService, explicitly pickle EventActions before passing to SQLAlchemy
  2. Option 2: Use SQLAlchemy's custom type with proper process_bind_param and process_result_value methods
  3. Option 3: Document pymysql incompatibility and recommend using mysqlclient or PostgreSQL instead

Additional Context

  • This issue does NOT occur with PostgreSQL
  • The problem is specific to the combination of SQLAlchemy 2.0 + pymysql + MySQL
  • The events table's actions column is defined as LONGBLOB in MySQL
  • Both writing (insert) and reading (deserialize) are affected

Questions

  1. Is MySQL with pymysql officially supported by ADK?
  2. If yes, should we expect this to work out of the box?
  3. Are there any plans to improve database driver compatibility testing?

Related Issues

  • Potentially related to SQLAlchemy 2.0 migration changes
  • May affect other BLOB columns in the schema (content, metadata fields, etc.)

Metadata

Metadata

Assignees

Labels

services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions