# Google ADK DatabaseSessionService: "TypeError: fromisoformat: argument must be str" on SQLite

*Disclosure: I work on MemorySync (I'm Mohammed, the founder). I drafted this page with AI assistance and checked it against the GitHub issue, the fix commit and the ADK source listed under Sources on Nov 11, 2026. Code status: I ran the repro offline on google-adk 2.3.0 (SQLAlchemy 2.0.41) and google-adk 2.14.0 (SQLAlchemy 2.1.8) with `sqlite+aiosqlite`, Python 3.13, no agent and no model. To get a float into the table I wrote it directly with Python's `sqlite3`; I didn't run `SqliteSessionService`, `adk web` or `adk api_server` against the same file, or any MemorySync code.*

You use ADK's `DatabaseSessionService` with a SQLite URL, and reading a session back fails:

```text
TypeError: fromisoformat: argument must be str
```

The traceback ends inside SQLAlchemy's `str_to_datetime`. That's google/adk-python issue [#6352](https://github.com/google/adk-python/issues/6352), "DatabaseSessionService.get_session() raises TypeError: fromisoformat: argument must be str", reported on google-adk 2.3.0.

MemorySync doesn't fix this bug. It's in how ADK's SQL session store reads timestamps, and you need the fix below with or without MemorySync.

> **Skip the memory plumbing around this fix.** Sessions are ADK's short-term store. Once they read back cleanly, the [MemorySync Google ADK guide](https://docs.memorysync.io/guides/google-adk?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str) shows a `BaseMemoryService` for memory that lasts across sessions. It doesn't replace your session service. When you're ready, [see MemorySync](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str). Founding offer: use code FOUNDING30 for 30% off Starter for your first 3 months (Settings → Billing).

## Status (Nov 11, 2026)

- [#6352](https://github.com/google/adk-python/issues/6352) was opened Jul 9, 2026 and **closed as completed** on Jul 16, 2026 by commit `2da09e6` ("fix: handle sqlite float timestamps in PreciseTimestamp", merging PR #6355).
- GitHub's compare view shows that commit included in the v2.5.0 and v2.6.0 tags. I ran 2.14.0 (the latest on PyPI on Nov 11, 2026), and it reads the same file without error.

## Why it happens

From the issue thread: ADK's SQL schema stores timestamps in a `PreciseTimestamp` column backed by SQLAlchemy `DateTime`. On SQLite, SQLAlchemy expects those values as text and parses them with `fromisoformat`. If a row holds a REAL (a Unix epoch float), the parser gets a float and raises.

How does a float get there? The thread's leading explanation, which the reporter confirmed, is a second writer: ADK's other SQLite backend, `SqliteSessionService`, stores timestamps as raw floats. If it and `DatabaseSessionService` touch the same database file, the SQL service can't read what the other one wrote. A maintainer also noted in the thread: "if SQLite is your main database we recommend just use the SqliteSessionService."

## Step 1: Reproduce it

This creates a session with `DatabaseSessionService`, puts a float in the `update_time` column (standing in for the other writer), then reads the session back with a fresh service:

```python
import asyncio, os, sqlite3, time
from google.adk.sessions import DatabaseSessionService

DB = "/tmp/adk_repro.db"
if os.path.exists(DB):
    os.remove(DB)

async def main():
    svc = DatabaseSessionService(db_url=f"sqlite+aiosqlite:///{DB}")
    await svc.create_session(app_name="app", user_id="u1", session_id="s1")

    con = sqlite3.connect(DB)
    con.execute("update sessions set update_time=? where id='s1'", (time.time(),))
    con.commit()
    con.close()

    svc2 = DatabaseSessionService(db_url=f"sqlite+aiosqlite:///{DB}")
    try:
        s = await svc2.get_session(app_name="app", user_id="u1", session_id="s1")
        print("OK", s.last_update_time)
    except Exception as e:
        print("FAILED", type(e).__name__, e)

asyncio.run(main())
```

You need the `db` extra: `pip install "google-adk[db]"` plus `aiosqlite`. What I got:

```text
google-adk 2.3.0, SQLAlchemy 2.0.41:  FAILED TypeError fromisoformat: argument must be str
google-adk 2.14.0, SQLAlchemy 2.1.8:  OK 1794409299.836908
```

## Step 2: Upgrade ADK

The fix overrides `result_processor` on `PreciseTimestamp` so a float is converted to a datetime before SQLAlchemy's text parser sees it. The thread explains why `process_result_value` alone wasn't enough: the base `DateTime` processor runs first and fails on the float.

```bash
pip install -U "google-adk[db]"
```

Then check that `result_processor` is defined in `google/adk/sessions/schemas/shared.py` in your installed package if you want to be sure you have the fix.

## Step 3: Use one session backend per database file

Upgrading stops the crash, but two services writing different timestamp formats into one file is still worth fixing:

- **SQLite only:** use `SqliteSessionService`, as the maintainer suggested, and point nothing else at that file.
- **Postgres, MySQL or another SQL database:** use `DatabaseSessionService`, and give it its own database.
- **`adk web` and `adk api_server`:** per a comment in the thread, both fall back to the same per-agent SQLite session store unless you pass `--session_service_uri`. If you pass it to one process and not the other, they can end up on different stores. Pass the same value to both.

## Skip the plumbing with MemorySync

Disclosure: I build MemorySync.

This doesn't change the fix above: `DatabaseSessionService` is still your session store, so upgrade it as in Step 2. The [MemorySync Google ADK guide](https://docs.memorysync.io/guides/google-adk?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str) documents `MemorySyncMemoryService`, an ADK `BaseMemoryService` you pass as `Runner(memory_service=...)` next to whatever `session_service` you use. You call `add_session_to_memory(session)` after a conversation, and ADK's `preload_memory` tool brings that user's memories into later sessions. It requires `google-adk` 2.0+ and Python 3.10+ and lists `google-adk-memorysync` 1.1.0.

From the guide:

**Unverified (not run):**

```bash
pip install google-adk-memorysync google-adk
```

```python
from google.adk.runners import Runner
from google_adk_memorysync import MemorySyncMemoryService

memory_service = MemorySyncMemoryService()  # reads MEMORYSYNC_API_KEY

runner = Runner(
    agent=agent,
    app_name="support",
    session_service=session_service,  # your DatabaseSessionService
    memory_service=memory_service,
)

# after a conversation:
session = await runner.session_service.get_session(
    app_name="support", user_id="customer-7", session_id="thread-42"
)
await memory_service.add_session_to_memory(session)
```

*Snippet adapted from the [MemorySync Google ADK guide](https://docs.memorysync.io/guides/google-adk?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str), which uses `InMemorySessionService`; I swapped in your session service and haven't run it for this page.*

**Try it:** MemorySync is optional here: the steps above work without it. If you want the memory layer from the snippet, [see MemorySync](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str), create an API key in the dashboard and drop the snippet into your agent.

## FAQ

**I deleted the database and it still fails. Why?**
The reporter saw the same thing. A fresh file only helps if nothing else writes floats into it; check every process and service that uses that path.

**Do I lose sessions by switching service?**
The two services use different schemas, so don't point a new service at the old file and expect it to read everything. Plan a migration or start a new file.

**Is this a SQLAlchemy bug?**
No. SQLAlchemy is doing what a `DateTime` column on SQLite does. The fix is on ADK's side, in `PreciseTimestamp`.

## Sources

- github.com/google/adk-python/issues/6352 (opened 2026-07-09, closed as completed 2026-07-16, 11 comments; root cause, `SqliteSessionService` float timestamps, maintainer recommendation, `--session_service_uri` note; read 2026-10-30)
- Commit 2da09e60d7d03d27bf9aa721db37cf0475157c21, "fix: handle sqlite float timestamps in PreciseTimestamp" (PR #6355), and GitHub compare against v2.5.0 and v2.6.0 (read 2026-10-30)
- google-adk 2.14.0 source: `google/adk/sessions/schemas/shared.py` (read 2026-11-11)
- Offline runs on google-adk 2.3.0 and 2.14.0, Python 3.13 (2026-11-11)
- MemorySync Google ADK guide: docs.memorysync.io/guides/google-adk (fetched 2026-10-30)

## Try it

For an overview of MemorySync, see [the MemorySync homepage](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str).

**Next step:** read the [MemorySync Google ADK guide](https://docs.memorysync.io/guides/google-adk?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str), then [see MemorySync](https://memorysync.io/?utm_source=hashnode&utm_medium=organic_page&utm_campaign=v5_oct25&utm_content=pseo_google-adk-databasesessionservice-fromisoformat-argument-must-be-str). Founding offer: use code FOUNDING30 for 30% off Starter for your first 3 months (Settings → Billing).
