Skip to content
Changelog

Database fixes for JsonDb and MongoDB

October 8, 20261 min read

Agno's JsonDb now serializes each table to a hidden .agno-json-<id>.tmp file in the same folder and publishes it with os.replace. Earlier releases opened the table itself in write mode first, so an error during json.dump left a cut-off file and every later read failed.

JsonDb keeps the last saved table when a write fails

We saved one session, then made the next write fail after its first byte with No space left on device. Real output on the previous release and on this one:

Before: write failed: [Errno 28] No space left on device
        file on disk: '['
        read failed: JSONDecodeError Expecting value: line 1 column 2 (char 1)
 
Now:    write failed: [Errno 28] No space left on device
        file on disk: '[\n  {\n    "session_id": "saved",\n    "ag'
        sessions: ['saved']

The failing write still raises, so your code hears about it. The staging file takes the existing table's owner and mode bits. When a path can't be replaced atomically, such as a bind-mounted table, a read-only folder or a table owned by another user, JsonDb falls back to writing the file in place. A table created for the first time uses an exclusive create, so it never truncates a table that a concurrent writer just published.

MongoDB filters match the text you typed

MongoDb.get_sessions(session_name=...), MongoDb.get_user_memories(search_content=...), the same two methods on AsyncMongoDb, and MongoVectorDb.keyword_search sent the caller's string to MongoDB as a $regex. A value with an unbalanced ( is an invalid pattern, so AgentOS answered GET /sessions and GET /memories with HTTP 500. A . matched any character, so v1.2 also found v1x2. Agno now runs each value through re.escape and keeps the case-insensitive flag.

Real output from MongoDb.get_sessions on an in-memory mongomock database holding Release v1.2 (draft) and Release v1x2 final:

Before: session_name='v1.2'   -> ['Release v1.2 (draft)', 'Release v1x2 final']
        session_name='(draft' -> error missing ), unterminated subpattern at position 0
 
Now:    session_name='v1.2'   -> ['Release v1.2 (draft)']
        session_name='(draft' -> ['Release v1.2 (draft)']

See the JsonDb cookbook and the MongoDB cookbook, and learn more about JsonDb, MongoDB storage and the MongoDB vector store in the documentation.

Frequently asked questions

Earlier releases opened the table file for writing before serializing it, so an error mid-write, such as a full disk, left a cut-off file and later reads raised JSONDecodeError. With this release JsonDb writes a staging file first and swaps it in only after serialization finishes.

Agno passed the raw session_name to MongoDB as a $regex, and an unbalanced ( is an invalid pattern. This release escapes the value, so the request returns the matching sessions.

Yes. Agno keeps the $options: "i" flag, so session_name, search_content and keyword search still ignore case. Only regex metacharacters such as ., ( and * now match themselves.

Shipped around the same time