openclaw - ✅(Solved) Fix QMD default memory collection can generate phantom `memory-alt-*` lookups when only `MEMORY.md` exists [2 pull requests, 1 comments, 2 participants]

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…
GitHub stats
openclaw/openclaw#65913Fetched 2026-04-14 05:39:39
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
cross-referenced ×2closed ×1commented ×1renamed ×1

With memory.backend = "qmd" and memory.qmd.includeDefaultMemory = true, OpenClaw can generate and later search a managed collection for lowercase memory.md even when the workspace only has uppercase MEMORY.md.

That can produce a phantom managed collection lookup like:

Collection not found: memory-alt-main

while QMD itself is otherwise healthy.

Root Cause

With memory.backend = "qmd" and memory.qmd.includeDefaultMemory = true, OpenClaw can generate and later search a managed collection for lowercase memory.md even when the workspace only has uppercase MEMORY.md.

That can produce a phantom managed collection lookup like:

Collection not found: memory-alt-main

while QMD itself is otherwise healthy.

Fix Action

Fix / Workaround

Current workaround

PR fix notes

PR #65914: fix(memory): respect qmd status timeout and skip checkpoint exports

Description (problem / solution / changelog)

Summary

This PR fixes two concrete QMD recall issues in extensions/memory-core/src/memory/qmd-manager.ts:

  1. probeVectorAvailability() now respects the configured memory.qmd.limits.timeoutMs
  2. QMD session export now excludes .checkpoint. transcript snapshots from exported session documents

Problem 1: false QMD vector-health failures

Before this change, probeVectorAvailability() hard-capped qmd status to 5 seconds:

const result = await this.runQmd(["status"], {
  timeoutMs: Math.min(this.qmd.limits.timeoutMs, 5_000),
});

That means a config like this:

{
  "memory": {
    "qmd": {
      "limits": { "timeoutMs": 10000 }
    }
  }
}

still timed out after 5 seconds during the status probe.

Why that matters

openclaw memory status and related vector-health checks can then report QMD as unavailable even when the underlying QMD index is healthy and just needs longer than 5 seconds to answer qmd status.

That is a misleading health signal, because the configured timeout is being ignored specifically on the probe path.

Fix

Use the configured timeout directly:

timeoutMs: this.qmd.limits.timeoutMs

Problem 2: checkpoint transcript noise in session recall

Before this change, exportSessions() iterated every session file returned by listSessionFilesForAgent(this.agentId) and exported all of them into the QMD session collection.

That included checkpoint snapshots like:

  • some-session.checkpoint.123.jsonl

Those files are valid recovery artifacts, but they are poor recall documents because they duplicate live session content and add noisy near-duplicates to semantic search.

Why this change is intentionally narrow

This PR excludes only .checkpoint. files at the QMD export layer:

const files = (await listSessionFilesForAgent(this.agentId)).filter((sessionFile) => {
  const baseName = path.basename(sessionFile);
  return !baseName.includes(".checkpoint.");
});

I kept this scoped to checkpoint snapshots because that is the cleanest low-risk duplicate class. I did not broaden the PR to other transcript artifact types here.

Validation

Added tests for both behaviors:

  • uses the configured qmd timeout for status probes
  • excludes checkpoint transcripts from exported qmd session documents

Ran:

pnpm vitest run extensions/memory-core/src/memory/qmd-manager.test.ts src/memory-host-sdk/host/session-files.test.ts

Result:

  • 2 test files passed
  • 91 tests passed

File references

Main code changes:

  • extensions/memory-core/src/memory/qmd-manager.ts:1179-1183
  • extensions/memory-core/src/memory/qmd-manager.ts:1918-1921

Added tests:

  • extensions/memory-core/src/memory/qmd-manager.test.ts

Related issue

Separate issue for a different QMD default-collection bug, not fixed in this PR:

  • #65913

Changed files

  • extensions/memory-core/src/memory/qmd-manager.test.ts (modified, +70/-0)
  • extensions/memory-core/src/memory/qmd-manager.ts (modified, +5/-2)

PR #66141: fix(memory): unify default root memory handling

Description (problem / solution / changelog)

Summary

  • treat workspace root memory as a single slot instead of separate MEMORY.md and memory.md default QMD collections
  • make QMD prefer exact MEMORY.md, fall back to legacy lowercase memory.md only when the canonical file is absent, and stop generating/searching phantom memory-alt-* collections
  • align builtin memory file discovery with the same uppercase-first fallback rule so both backends share one root-memory model
  • harden QMD upgrade/rebind logic so legacy memory-alt collections that still own the root slot can be rebound to memory-root-* during repair

Why

OpenClaw had real source-of-truth drift around default root memory handling. The workspace/bootstrap rules already treat lowercase memory.md as legacy fallback only, but the QMD default collection resolver still modeled it as a second default collection. That let runtime search and repair target phantom memory-alt-* collections when only MEMORY.md existed.

User impact

  • removes noisy phantom QMD lookups and fallback-to-builtin behavior for normal MEMORY.md workspaces
  • keeps lowercase-only legacy workspaces working
  • makes builtin and QMD root-memory behavior consistent

Validation

  • pnpm test -- packages/memory-host-sdk/src/host/internal.test.ts
  • pnpm test -- packages/memory-host-sdk/src/host/backend-config.test.ts
  • pnpm test -- extensions/memory-core/src/memory/qmd-manager.test.ts
  • commit hook passed pnpm check

Related

  • #65913
  • #65908
  • #65890

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/memory-core/src/memory/qmd-manager.test.ts (modified, +165/-0)
  • extensions/memory-core/src/memory/qmd-manager.ts (modified, +73/-5)
  • packages/memory-host-sdk/src/host/backend-config.test.ts (modified, +88/-3)
  • packages/memory-host-sdk/src/host/backend-config.ts (modified, +35/-2)
  • packages/memory-host-sdk/src/host/internal.test.ts (modified, +19/-0)
  • packages/memory-host-sdk/src/host/internal.ts (modified, +25/-4)

Code Example

Collection not found: memory-alt-main

---

// packages/memory-host-sdk/src/host/backend-config.ts
const entries = [
  { path: workspaceDir, pattern: "MEMORY.md", base: "memory-root" },
  { path: workspaceDir, pattern: "memory.md", base: "memory-alt" },
  { path: path.join(workspaceDir, "memory"), pattern: "**/*.md", base: "memory-dir" },
];

---

// src/memory-host-sdk/host/backend-config.ts
const entries = [
  { path: workspaceDir, pattern: "MEMORY.md", base: "memory-root" },
  { path: path.join(workspaceDir, "memory"), pattern: "**/*.md", base: "memory-dir" },
];

---

{
  "memory": {
    "backend": "qmd",
    "qmd": {
      "command": "/opt/homebrew/bin/qmd",
      "includeDefaultMemory": true,
      "sessions": { "enabled": true },
      "limits": { "timeoutMs": 10000 }
    }
  }
}

---

memory-alt-main

---

Collection not found: memory-alt-main

---

{
  "memory": {
    "backend": "qmd",
    "qmd": {
      "includeDefaultMemory": false,
      "paths": [
        { "name": "memory-root", "path": "/path/to/workspace", "pattern": "MEMORY.md" },
        { "name": "memory-dir", "path": "/path/to/workspace/memory", "pattern": "**/*.md" }
      ]
    }
  }
}
RAW_BUFFERClick to expand / collapse

Summary

With memory.backend = "qmd" and memory.qmd.includeDefaultMemory = true, OpenClaw can generate and later search a managed collection for lowercase memory.md even when the workspace only has uppercase MEMORY.md.

That can produce a phantom managed collection lookup like:

Collection not found: memory-alt-main

while QMD itself is otherwise healthy.

Why I think this is a real bug, not bad local state

In this repo checkout there is a concrete source inconsistency around default QMD collection generation:

  • packages/memory-host-sdk/src/host/backend-config.ts:330-333 still declares three default entries:
    • MEMORY.md -> memory-root
    • memory.md -> memory-alt
    • memory/ -> memory-dir
  • src/memory-host-sdk/host/backend-config.ts:337-340 only declares:
    • MEMORY.md -> memory-root
    • memory/ -> memory-dir

So at least one code path in the tree still models lowercase memory.md as a default managed collection, while another does not.

Relevant lines from this checkout:

// packages/memory-host-sdk/src/host/backend-config.ts
const entries = [
  { path: workspaceDir, pattern: "MEMORY.md", base: "memory-root" },
  { path: workspaceDir, pattern: "memory.md", base: "memory-alt" },
  { path: path.join(workspaceDir, "memory"), pattern: "**/*.md", base: "memory-dir" },
];

but:

// src/memory-host-sdk/host/backend-config.ts
const entries = [
  { path: workspaceDir, pattern: "MEMORY.md", base: "memory-root" },
  { path: path.join(workspaceDir, "memory"), pattern: "**/*.md", base: "memory-dir" },
];

There is also a matching test expectation in packages/memory-host-sdk/src/host/backend-config.test.ts:39-42 that still expects memory-alt-main to exist by default.

That matches the failure seen in a real install: published/runtime code can still end up generating or searching memory-alt-* even when lowercase memory.md is absent.

Environment

  • OpenClaw: 2026.4.11 on macOS
  • QMD: 2.1.0
  • install style: global install / gateway restart
  • workspace has MEMORY.md
  • workspace does not have lowercase memory.md
  • memory backend: qmd

Relevant config shape

{
  "memory": {
    "backend": "qmd",
    "qmd": {
      "command": "/opt/homebrew/bin/qmd",
      "includeDefaultMemory": true,
      "sessions": { "enabled": true },
      "limits": { "timeoutMs": 10000 }
    }
  }
}

Repro

  1. Use a workspace containing MEMORY.md and memory/, but no lowercase memory.md
  2. Configure memory.backend = "qmd"
  3. Leave memory.qmd.includeDefaultMemory = true
  4. Restart OpenClaw
  5. Trigger QMD-backed recall or status paths

Actual behavior

OpenClaw can try to use a managed collection named like:

memory-alt-main

for lowercase memory.md, even though that file does not exist.

Observed failure:

Collection not found: memory-alt-main

At the same time, the actual QMD index can still be healthy. In my case the live QMD collections were the expected real ones only:

  • memory-root-main
  • memory-dir-main
  • sessions-main
  • basecamp

with no valid reason for a memory-alt-main lookup.

Expected behavior

If the workspace has MEMORY.md but not lowercase memory.md, OpenClaw should not create, repair, or search a managed memory-alt-* default collection.

More generally, default managed collections should only be generated for paths that are actually part of the active default set.

Current workaround

Disable default-memory auto-generation and declare explicit QMD paths instead:

{
  "memory": {
    "backend": "qmd",
    "qmd": {
      "includeDefaultMemory": false,
      "paths": [
        { "name": "memory-root", "path": "/path/to/workspace", "pattern": "MEMORY.md" },
        { "name": "memory-dir", "path": "/path/to/workspace/memory", "pattern": "**/*.md" }
      ]
    }
  }
}

That avoided the bad default collection resolution and restored working recall on the real path.

Suggested fix direction

The smallest fix seems to be:

  • remove lowercase memory.md from the default QMD collection set wherever it still exists, or
  • at minimum only emit/search memory-alt-* when that file actually exists

But the bigger thing to fix is the duplication drift: the source tree should not have one default-collection definition that includes memory-alt and another that does not.

extent analysis

TL;DR

The most likely fix is to remove lowercase memory.md from the default QMD collection set or only emit/search memory-alt-* when the file actually exists.

Guidance

  • Review and update the default QMD collection definitions in packages/memory-host-sdk/src/host/backend-config.ts and src/memory-host-sdk/host/backend-config.ts to ensure consistency and remove references to lowercase memory.md.
  • Verify that the memory-alt-main collection is not generated or searched when the workspace only contains MEMORY.md and no lowercase memory.md.
  • Consider implementing a check to only emit/search memory-alt-* when the corresponding file exists in the workspace.
  • Update the test expectation in packages/memory-host-sdk/src/host/backend-config.test.ts to reflect the corrected default collection behavior.

Example

No code snippet is provided as the issue is more related to configuration and consistency rather than a specific code fix.

Notes

The issue seems to be caused by inconsistent default collection definitions in the source tree, leading to unexpected behavior when searching for managed collections. The suggested fix direction is to remove the duplication drift and ensure that the default collection set only includes paths that are actually part of the active default set.

Recommendation

Apply the workaround by disabling default-memory auto-generation and declaring explicit QMD paths instead, as described in the issue, until a permanent fix is implemented. This will avoid the bad default collection resolution and restore working recall on the real path.

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…

FAQ

Expected behavior

If the workspace has MEMORY.md but not lowercase memory.md, OpenClaw should not create, repair, or search a managed memory-alt-* default collection.

More generally, default managed collections should only be generated for paths that are actually part of the active default set.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING