Pull Request: Fix Critical Timer/Database Race Conditions During Plugin Shutdown

To create this PR, go to: https://github.com/markus-lassfolk/openclaw-hybrid-memory/compare/main…claude/identify-critical-bug-scope

Then copy the content below into the PR description.


Summary

This PR fixes critical race conditions where background timers and deferred operations (setImmediate, setTimeout, setInterval) access closed database connections during plugin shutdown or reload, preventing process crashes and silent data loss.

Critical Bug Fixed

Race Condition Between setImmediate Database Operations and Plugin Shutdown

  • Severity: Critical - Can cause Node.js process crashes or silent data loss
  • Root Cause: Deferred operations executing after database connections close
  • Impact: Hebbian links not strengthened, process crashes, degraded memory graph quality

Changes Made

Code Fixes (5 actual bugs)

  1. lifecycle/stage-injection.ts - Added database connection check before Hebbian link strengthening in setImmediate callback, plus error suppression for expected shutdown errors
  2. lifecycle/stage-cleanup.ts - Enhanced error handling to suppress expected database connection errors during shutdown in stale session sweep
  3. setup/plugin-service.ts - Added factsDb.isOpen() checks to classify timer, passive observer timer, and watchdog timer
  4. index.ts - Added database connection check before cron verification in setImmediate callback
  5. services/python-bridge.ts - Improved timer cleanup in shutdown method to clear pending request timers

Documentation

  • TIMER_RACE_CONDITIONS_ANALYSIS.md - Comprehensive technical analysis of all 11 issues identified, including false positives and already-handled cases
  • .github/ISSUE_TEMPLATE/timer-manager-enhancement.md - Detailed enhancement proposal for optional centralized TimerManager utility
  • docs/ENHANCEMENT_TIMER_MANAGER.md - User-friendly version of enhancement issue ready to file

Files Modified

  • extensions/memory-hybrid/lifecycle/stage-injection.ts
  • extensions/memory-hybrid/lifecycle/stage-cleanup.ts
  • extensions/memory-hybrid/setup/plugin-service.ts
  • extensions/memory-hybrid/index.ts
  • extensions/memory-hybrid/services/python-bridge.ts
  • TIMER_RACE_CONDITIONS_ANALYSIS.md (new)
  • .github/ISSUE_TEMPLATE/timer-manager-enhancement.md (new)
  • docs/ENHANCEMENT_TIMER_MANAGER.md (new)

Investigation Summary

Analysis identified 11 potential issues in timer/database lifecycle management:

  • 5 actual bugs fixed (race conditions, missing guards, improper cleanup)
  • 2 already handled (proper guards already in place)
  • 3 false positives (client-side code, proper AbortController usage)
  • ⏭️ 1 enhancement proposal (optional centralized TimerManager for future work)

Testing Required

Before merging, please run:

cd extensions/memory-hybrid
npm ci
npm run lint
npm run build
npm run test

Impact

This fix prevents the “database connection is not open” errors that can occur during plugin shutdown or reload. All background timers and deferred operations now properly check database connection state before executing.

Success Metrics

  • Eliminates process crashes during plugin shutdown
  • Prevents silent data loss in Hebbian link strengthening
  • Reduces “database connection is not open” errors in logs
  • Ensures graceful degradation during shutdown

Before & After

Before

setImmediate(() => {
  try {
    factsDb.strengthenRelatedLinksBatch(pairs);  // ❌ May crash if DB closed
  } catch (err) {
    // Error handling present but too late
  }
});

After

setImmediate(() => {
  try {
    // ✅ Check database state first
    if (typeof factsDb.isOpen === "function" && !factsDb.isOpen()) {
      return;
    }
    factsDb.strengthenRelatedLinksBatch(pairs);
  } catch (err) {
    const e = err instanceof Error ? err : new Error(String(err));
    // ✅ Suppress expected shutdown errors
    if (!/database connection is not open/i.test(e.message)) {
      capturePluginError(e, { operation: "hebbian-strengthen", subsystem: "stage-injection" });
      logger.warn(`memory-hybrid: hebbian link strengthening failed: ${err}`);
    }
  }
});
  • See TIMER_RACE_CONDITIONS_ANALYSIS.md for complete technical details
  • Enhancement proposal for centralized timer management available in docs/ENHANCEMENT_TIMER_MANAGER.md
  • Addresses patterns identified across 150+ timer call sites in the codebase

Checklist

  • Code changes implement fixes for all identified critical bugs
  • Added database connection guards to all high-risk timers
  • Enhanced error handling to suppress expected shutdown errors
  • Comprehensive documentation of analysis and fixes
  • Enhancement proposal for future centralized timer management
  • Tests pass (requires npm ci && npm test in extensions/memory-hybrid)
  • No regressions in plugin shutdown behavior

🤖 Generated with Claude Code


Back to top

OpenClaw Hybrid Memory — durable agent memory

This site uses Just the Docs, a documentation theme for Jekyll.