Skip to content

SqliteMemoryService can't find a stored word that starts with a capital dotted I (İ) #7540

Closed

Description

@Somay-kousis

🔴 Required Information

Describe the Bug:

SqliteMemoryService stores an event with the text "İstanbul trip". Searching for "İstanbul" returns nothing. Same in FTS mode and LIKE mode. Any word with a capital dotted I is affected, so most Turkish and Azerbaijani text with a capitalized İ can't be found by that word.

Steps to Reproduce:

  1. pip install google-adk (or a checkout of main)
  2. Save the script below as repro.py
  3. Run python repro.py

Expected Behavior:

Searching for "İstanbul" returns the event, like searching for "trip" does.

Observed Behavior:

fts=on query='İstanbul' hits=0
fts=on query='trip' hits=1
fts=off query='İstanbul' hits=0
fts=off query='trip' hits=1

Environment Details:

  • ADK Library Version (pip show google-adk): 2.12.0, main at 29bb053
  • Desktop OS: macOS 26.6
  • Python Version (python -V): Python 3.12.13 (SQLite 3.53.4)

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A, no model call needed

🟡 Optional Information

Regression:

No. It has been there since SqliteMemoryService was added in 9625b06.

Root cause:

Indexing and querying normalize text in a different order.

  • When it stores an event, add_events_to_memory lowercases first and then calls _split_script_runs (src/google/adk/memory/_sqlite_memory_service.py:329-330).
  • When it searches, _extract_tokens calls _split_script_runs first and lowercases each token after (_sqlite_memory_service.py:531-535).

In Python, "İ".lower() is two characters: "i" and U+0307 COMBINING DOT ABOVE. U+0307's Unicode name doesn't start with LATIN, so _is_latin (_sqlite_memory_service.py:510-513) returns False for it and _split_script_runs cuts the word there. "İstanbul" gets indexed as "i ̇ stanbul", while the query token is "i̇stanbul". Neither FTS nor LIKE can match the two.

I checked every code point: U+0130 is the only Latin character whose lowercase contains a non-Latin character, so this is the only letter hit.

Minimal Reproduction Code:

import asyncio

from google.adk.events.event import Event
from google.adk.memory import SqliteMemoryService
from google.genai import types


async def main() -> None:
  for fts in ("on", "off"):
    service = SqliteMemoryService(":memory:", fts=fts)
    await service.add_events_to_memory(
        app_name="app",
        user_id="user",
        session_id="s1",
        events=[
            Event(
                id="e1",
                author="user",
                timestamp=1.0,
                content=types.Content(
                    role="user", parts=[types.Part(text="İstanbul trip")]
                ),
            )
        ],
    )
    for query in ("İstanbul", "trip"):
      response = await service.search_memory(
          app_name="app", user_id="user", query=query
      )
      print(f"fts={fts} query={query!r} hits={len(response.memories)}")
    await service.close()


asyncio.run(main())

How often has this issue occurred?:

  • Always (100%)

I have a fix with a regression test ready and will open a PR.

Activity

  1. surajksharma07 commented on Oct 15, 2026

    @surajksharma07
    Collaborator

    @Somay-kousis Reproduced this on main (2.12.0) on Windows/SQLite 3.45 too so it isn't platform specific.

    Your reorder in #7541 fixes it on my side in both FTS and LIKE mode and the existing memory tests still pass. For anyone stuck on 2.11/2.12 meanwhile patching _is_latin to also accept "̇" works as a stopgap.

    One thing worth calling out: rows indexed before the fix stay unsearchable until re-added so a short note in the PR description would help.

    Could you also give it a quick run with some mixed-script text (Turkish + CJK/Hindi) to be sure nothing else shifts? Once that looks good we'll push #7541 for review.

  2. Somay-kousis commented on Oct 15, 2026

    @Somay-kousis
    ContributorAuthor

    Thanks for checking it on Windows.

    Ran a mixed-script check on main and on #7541: 8 stored events mixing Turkish (İ, ı), CJK, Hindi, Cyrillic and accented Latin, 25 queries, FTS and LIKE mode.

    • Queries for 東京, 直行便, 北京, दिल्ली, यात्रा, मुंबई, Mumbai, Дмитрий, café, résumé, ılık, planı, trip and 2026 return the same events on both.
    • The only changes are hits on stored words that start with İ (İstanbul, İzmir, İnce, İyi, İvan), and they only gain hits. İzmir in "İzmir और दिल्ली की यात्रा" goes from 0 to 1. İstanbul in "東京İstanbul直行便" now matches in both modes. In FTS mode istanbul and ince find them too.
    • Not changed by this PR: in LIKE mode a plain istanbul still won't match "İstanbul". Same on main.

    The note about rows indexed before the fix is in the PR description, under Solution.

  3. surajksharma07 commented on Oct 15, 2026

    @surajksharma07
    Collaborator

    Matches what I see @Somay-kousis. On 9706f50 I get 48/48 in test_sqlite_memory_service.py and a mixed Turkish/CJK/Hindi/Cyrillic run only changes the İ hits, same as yours.

    Small nit for the description: scanned every code point and U+2183 (Ↄ) also indexes differently now. Its lowercase is Latin so it gets split off from neighbouring Latin letters. That just matches what the query side already does so "abↃcd" now matches in FTS mode too (0 -> 1). It’s harmless but it means U+0130 isn’t strictly the only one.

    Agreed that the LIKE-mode "istanbul" vs "İstanbul" gap is pre-existing and out of scope here, it can be its own issue if anyone hits it.

    Nothing else from my side. Will flag #7541 for maintainer review.

  4. Somay-kousis commented on Oct 15, 2026

    @Somay-kousis
    ContributorAuthor

    Good catch on Ↄ, thanks. I reran a scan over every code point and it finds one more: U+03A3 Σ. Lowercasing the whole string picks final ς when Σ ends a word glued to Latin letters (abΣ becomes abς), while splitting first gives ab σ, which is what the query side already produces. Same as Ↄ, searches only gain hits, and plain Greek words like ΟΔΥΣΣΕΥΣ index the same as before.

    Updated the PR description to list all three.

  5. surajksharma07 commented on Oct 15, 2026

    @surajksharma07
    Collaborator

    Nice find @Somay-kousis, my scan only put each char alone or mid-word so it never hit the word-final σ/ς case. With end-of-word positions added I get exactly the same three: U+0130, U+03A3 and U+2183.

    Also checked Σ end to end: storing "abΣ note" and querying Σ/σ goes from 1 to 2 hits in LIKE mode, FTS is unchanged (it already matched) and ΟΔΥΣΣΕΥΣ/οδυσσευς return the same as on main. So it only gains hits as you said.

    The code is still the same single commit and the updated description covers everything. All good from my side, #7541 is flagged for maintainer review.

  6. added a commit that references this issue on Oct 15, 2026
    2416f66
  7. added
    services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc
    on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

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