From c03acca508bd06c78761af2653ebef1a1448b307 Mon Sep 17 00:00:00 2001 From: yifengingit <37467487+yifengingit@users.noreply.github.com> Date: Thu, 14 May 2026 07:57:47 -0700 Subject: [PATCH] fix: use AUTOINCREMENT id for message ordering instead of timestamp On WSL2 (and similar environments), time.time() is not strictly monotonic due to NTP sync or host clock adjustments. When clock regression occurs during a multi-tool flush, later-inserted rows get earlier timestamps, causing ORDER BY timestamp, id to sort them before rows that were written first. This breaks the tool_calls/tool_response adjacency invariant and triggers HTTP 400 from the API. Use ORDER BY id instead, since id (INTEGER PRIMARY KEY AUTOINCREMENT) always reflects true insertion order regardless of system clock behavior. --- hermes_state.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hermes_state.py b/hermes_state.py index adbdff19ac9..f693f391f78 100644 --- a/hermes_state.py +++ b/hermes_state.py @@ -1597,10 +1597,10 @@ class SessionDB: self._execute_write(_do) def get_messages(self, session_id: str) -> List[Dict[str, Any]]: - """Load all messages for a session, ordered by timestamp.""" + """Load all messages for a session, ordered by insertion order.""" with self._lock: cursor = self._conn.execute( - "SELECT * FROM messages WHERE session_id = ? ORDER BY timestamp, id", + "SELECT * FROM messages WHERE session_id = ? ORDER BY id", (session_id,), ) rows = cursor.fetchall() @@ -1700,7 +1700,7 @@ class SessionDB: "SELECT role, content, tool_call_id, tool_calls, tool_name, " "finish_reason, reasoning, reasoning_content, reasoning_details, " "codex_reasoning_items, codex_message_items " - f"FROM messages WHERE session_id IN ({placeholders}) ORDER BY timestamp, id", + f"FROM messages WHERE session_id IN ({placeholders}) ORDER BY id", tuple(session_ids), ).fetchall()