Bug Description
MemoryStore.replace() refuses an ambiguous replace when old_text substring-matches two or more entries ("Multiple entries matched"), which is correct on its own. But when the model's intended replacement text is already present verbatim as a separate entry, that generic error sets a trap: the model's natural fallback is add(), which then creates a duplicate of the entry that already said what it wanted to write. The model never gets a signal that the fact it wanted to record already exists.
add() already guards the simpler case - exact duplicates are rejected with "Entry already exists (no duplicate added)", but the replace path gives no equivalent hint, so the duplicate arrives via the replace → add two-step.
Observed as a repeatable tool-misuse pattern running a local model (qwen3.6-35b) against the file memory store: replace → ambiguous match → fallback add → duplicate entry.
Steps to Reproduce
- Seed the file memory store with two entries sharing a substring (e.g. both containing "prefers dark mode") and a third entry whose text is exactly what the model would write as the update.
- Call
memory(action="replace", old_text="prefers dark mode", new_content=<the third entry's exact text>).
- Get the generic "Multiple entries matched" error.
- Call
memory(action="add", content=<same text>) with content differing even trivially from the existing entry (whitespace, punctuation), a duplicate is stored.
Expected Behavior
When an ambiguous replace's new_content already exists verbatim as a separate entry, the error should say so and point at a batch operations call to disambiguate instead of the generic ambiguity message, that invites a duplicate-creating add().
Actual Behavior
Generic "Multiple entries matched" error, then a duplicate entry after the fallback add.
Affected Component
Agent Core (conversation loop, context compression, memory)
Messaging Platform (if gateway-related)
No response
Debug Report
Not attaching "hermes debug share" links for this one: it's a code-level behavior
gap in tools/memory_tool.py, fully reproducible from unit tests and not
environment-specific, and my recent logs contain private gateway-session content.
Confirmed the gap still exists on current main by inspection — replace() returns
the generic ambiguity error with no check against existing entry content. Happy
to share specific redacted log excerpts on request.
System info (from "hermes debug share --local"):
version: 0.18.0 (2026.7.1)
os: Darwin 25.4.0 arm64 (macOS 15, Apple Silicon)
python: 3.11.15
openai_sdk: 2.24.0
provider: lmstudio (local OpenAI-compatible endpoint)
model: Qwen3.6-35B-A3B-MLX-8bit
toolsets: hermes-cli
memory: built-in
gateway: telegram
Operating System
macOS 15
Python Version
3.11.15
Hermes Version
0.18.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
No response
Are you willing to submit a PR for this?
Bug Description
MemoryStore.replace()refuses an ambiguous replace whenold_textsubstring-matches two or more entries ("Multiple entries matched"), which is correct on its own. But when the model's intended replacement text is already present verbatim as a separate entry, that generic error sets a trap: the model's natural fallback isadd(), which then creates a duplicate of the entry that already said what it wanted to write. The model never gets a signal that the fact it wanted to record already exists.add()already guards the simpler case - exact duplicates are rejected with"Entry already exists (no duplicate added)", but the replace path gives no equivalent hint, so the duplicate arrives via the replace → add two-step.Observed as a repeatable tool-misuse pattern running a local model (qwen3.6-35b) against the file memory store: replace → ambiguous match → fallback add → duplicate entry.
Steps to Reproduce
memory(action="replace", old_text="prefers dark mode", new_content=<the third entry's exact text>).memory(action="add", content=<same text>)with content differing even trivially from the existing entry (whitespace, punctuation), a duplicate is stored.Expected Behavior
When an ambiguous replace's
new_contentalready exists verbatim as a separate entry, the error should say so and point at a batchoperationscall to disambiguate instead of the generic ambiguity message, that invites a duplicate-creatingadd().Actual Behavior
Generic "Multiple entries matched" error, then a duplicate entry after the fallback add.
Affected Component
Agent Core (conversation loop, context compression, memory)
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
macOS 15
Python Version
3.11.15
Hermes Version
0.18.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
No response
Are you willing to submit a PR for this?