hermes - 💡(How to fix) Fix Memory provider (holographic) silent failure: corrupted DB causes dead tools with no user-facing error [2 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When memory_store.db gets corrupted (e.g., due to abnormal shutdown during WAL checkpoint), the holographic memory provider fails initialization silently. The fact_store and fact_feedback tools remain registered but are completely broken — every call returns a cryptic 'NoneType' object has no attribute 'xxx' error. The user never receives any chat-level warning. This went undetected for 18 days / 300+ session initializations in production.

Error Message

MemoryStore.init() # No try/except → _init_db() → sqlite3 "file is not a database" ↓ HolographicMemoryProvider.initialize() # No try/except
↓ memory_manager.initialize_all() # Catches the exception but only logs WARNING ↓ Tools stay registered, _store = None # User sees nothing — tools silently dead

Root Cause

The failure chain has no guardrails:

MemoryStore.__init__()                     # No try/except
    → _init_db() → sqlite3 "file is not a database"
HolographicMemoryProvider.initialize()     # No try/except  
memory_manager.initialize_all()            # Catches the exception but only logs WARNING
Tools stay registered, _store = None       # User sees nothing — tools silently dead

Every subsequent fact_store / fact_feedback call hits self._store.<method>() where _store is None, producing un-actionable Python AttributeError.

Fix Action

Fixed

Code Example

MemoryStore.__init__()                     # No try/except
_init_db() → sqlite3 "file is not a database"
HolographicMemoryProvider.initialize()     # No try/except  
memory_manager.initialize_all()            # Catches the exception but only logs WARNING
Tools stay registered, _store = None       # User sees nothing — tools silently dead

---

dd if=/dev/urandom of=memory_store.db bs=1 count=11 seek=5 conv=notrunc

---

def _handle_fact_store(self, args: dict) -> str:
    if self._store is None:
        return tool_error(
            "holographic memory is unavailable — the database may be corrupted. "
            "Try deleting ~/.hermes/memory_store.db and restarting Hermes."
        )
    # ... rest of handler

---

# In MemoryStore.__init__:
try:
    self._conn = sqlite3.connect(str(self.db_path), ...)
    self._init_db()
except sqlite3.DatabaseError as e:
    if "not a database" in str(e):
        logger.warning("memory_store.db corrupted, recreating...")
        self.db_path.unlink(missing_ok=True)
        self._conn = sqlite3.connect(str(self.db_path), ...)
        self._init_db()
    else:
        raise

---

def system_prompt_block(self) -> str:
    if not self._store:
        return "# Holographic Memory\n⚠️ UNAVAILABLE — database is corrupted"
    # ... existing code
RAW_BUFFERClick to expand / collapse

Memory provider (holographic) silent failure: corrupted DB causes dead tools with no user-facing error

Summary

When memory_store.db gets corrupted (e.g., due to abnormal shutdown during WAL checkpoint), the holographic memory provider fails initialization silently. The fact_store and fact_feedback tools remain registered but are completely broken — every call returns a cryptic 'NoneType' object has no attribute 'xxx' error. The user never receives any chat-level warning. This went undetected for 18 days / 300+ session initializations in production.

Root Cause

The failure chain has no guardrails:

MemoryStore.__init__()                     # No try/except
    → _init_db() → sqlite3 "file is not a database"
HolographicMemoryProvider.initialize()     # No try/except  
memory_manager.initialize_all()            # Catches the exception but only logs WARNING
Tools stay registered, _store = None       # User sees nothing — tools silently dead

Every subsequent fact_store / fact_feedback call hits self._store.<method>() where _store is None, producing un-actionable Python AttributeError.

Steps to Reproduce

  1. Corrupt the memory_store.db header (simulating crash during WAL write):
    dd if=/dev/urandom of=memory_store.db bs=1 count=11 seek=5 conv=notrunc
  2. Start Hermes
  3. Check system prompt → still says "Holographic Memory: Active"
  4. Call fact_store(action='list')'NoneType' object has no attribute 'list_facts'
  5. No visible error in chat — only a single WARNING line buried in errors.log

Expected vs Actual

AspectExpectedActual
User notificationChat message or system prompt warningNothing visible
Tool behaviorUnregistered, or clear error messageRegistered, cryptic AttributeError
Auto-recoveryDetect corrupt DB and recreateManual hex-editing required
Log visibilityErrors.log only✅ (same)

Affected Code

  • agent/memory_manager.py L602-609initialize_all() silently swallows init failure, tools stay registered
  • plugins/memory/holographic/__init__.py L259-L344_handle_fact_store / _handle_fact_feedback access self._store with no null-check
  • plugins/memory/holographic/store.py L101-122MemoryStore.__init__ has no error recovery for corrupt database
  • plugins/memory/holographic/__init__.py L183-204system_prompt_block() reports "Active" even when _store is None

Proposed Fix

1. Null guard in tool handlers (minimal, highest impact)

def _handle_fact_store(self, args: dict) -> str:
    if self._store is None:
        return tool_error(
            "holographic memory is unavailable — the database may be corrupted. "
            "Try deleting ~/.hermes/memory_store.db and restarting Hermes."
        )
    # ... rest of handler

Same for _handle_fact_feedback.

2. Auto-recover from corrupt database

# In MemoryStore.__init__:
try:
    self._conn = sqlite3.connect(str(self.db_path), ...)
    self._init_db()
except sqlite3.DatabaseError as e:
    if "not a database" in str(e):
        logger.warning("memory_store.db corrupted, recreating...")
        self.db_path.unlink(missing_ok=True)
        self._conn = sqlite3.connect(str(self.db_path), ...)
        self._init_db()
    else:
        raise

3. Honest system prompt

def system_prompt_block(self) -> str:
    if not self._store:
        return "# Holographic Memory\n⚠️ UNAVAILABLE — database is corrupted"
    # ... existing code

4. (Optional) Initialize failure should unregister tools

In initialize_all(), if a provider fails init, consider removing it from _providers and _tool_to_provider so the agent doesn't try to use dead tools.

Environment

  • Hermes Agent (git main, May 2026)
  • Python 3.11.15, SQLite 3.50.4
  • OS: Ubuntu 24.04, ext4 filesystem
  • Memory provider: holographic (default in config.yaml)

Real-world Impact

  • 18 days of silent failure in production use
  • 300+ session initializations all logged the same WARNING — user never noticed
  • 40 stored facts were inaccessible during this period (manually recovered by hex-editing the file header)
  • Every fact_store/fact_feedback call returned unhelpful AttributeError responses, wasting LLM tokens on retries and confusing the agent

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING