You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
qmd update keeps the old content of a file that became empty #991
When an indexed markdown file is emptied (truncated to zero bytes or to whitespace only), qmd update skips it silently, counting it under no bucket, and its previous body stays active in the index. search, query and get keep returning content that no longer exists on disk. A file that is deleted is deactivated correctly; a file that is emptied is not.
export QMD_CONFIG_DIR=/tmp/qmd-cfg INDEX_PATH=/tmp/qmd-index.sqlite
mkdir -p /tmp/notes &&printf'# A\n\nzebra body\n'> /tmp/notes/a.md
qmd collection add /tmp/notes --name notes # Indexed: 1 new:> /tmp/notes/a.md # file is now empty
qmd update # Indexed: 0 new, 0 updated, 0 unchanged, 0 removed
qmd search zebra # still returns "zebra body"
qmd get qmd://notes/a.md # still returns the old body
Cause
In reindexCollection (src/store.ts) the path is added to seenPaths before the empty-content check. The empty check then continues, so the existing row is never updated and the end-of-pass deactivation skips it because the path counts as seen.
Suggested fix
Treat an emptied file the way a deleted file is treated: do not count it as seen, so the deactivation pass at the end marks the row inactive. Writing content back reactivates it through the normal insert path. Empty files at first index are already skipped, so this makes the two cases consistent.
I have a small fix with a test ready and will open a PR.
Confirmed on the latest published release (2.8.3, released 2026-08-16): the empty-file behaviour described here still reproduces, so the fix that is now on main is not shipped yet.
Repro on 2.8.3 (facd35e):
printf'#decision use Redis'>~/mem/MEMORY.md
qmd collection add ~/mem --name mem # indexed 1:>~/mem/MEMORY.md # file emptied to 0 bytes
qmd update # Indexed: 0 new, 0 updated, 1 unchanged, 0 removed
qmd ls mem # still lists MEMORY.md at the old byte size
qmd search "Redis" -c mem # still returns the removed body
qmd get qmd://mem/MEMORY.md # still returns it
qmd cleanup # reclaims orphan vectors only; the doc stays active
rm ~/mem/MEMORY.md && qmd update # "1 removed" - only removing the file deactivates it
On main, src/store.ts now has retireIndexedFile handling a path that "became empty or grew past REINDEX_MAX_FILE_SIZE", so the fix exists upstream. #992 was closed without merge (merged_at: null), so the change appears to have landed via a commit rather than that PR. Either way, anyone on the latest npm release is still affected.
Why it matters in practice: memory/agent tooling rewrites files in place and can legitimately truncate one to zero entries. When that happens the old body stays active and keeps being returned by search, query and get - deleted facts remain retrievable, which is a correctness hazard, not just stale metadata.
Suggestion: cut a release that includes retireIndexedFile, or at minimum document the requirement, since 2.8.3 is the only version most installs resolve to.
Activity
fix(update): deactivate a document whose file became empty
yakold commentedon Nov 14, 2026
Confirmed on the latest published release (2.8.3, released 2026-08-16): the empty-file behaviour described here still reproduces, so the fix that is now on
mainis not shipped yet.Repro on 2.8.3 (
facd35e):On
main,src/store.tsnow hasretireIndexedFilehandling a path that "became empty or grew past REINDEX_MAX_FILE_SIZE", so the fix exists upstream. #992 was closed without merge (merged_at: null), so the change appears to have landed via a commit rather than that PR. Either way, anyone on the latest npm release is still affected.Why it matters in practice: memory/agent tooling rewrites files in place and can legitimately truncate one to zero entries. When that happens the old body stays active and keeps being returned by
search,queryandget- deleted facts remain retrievable, which is a correctness hazard, not just stale metadata.Suggestion: cut a release that includes
retireIndexedFile, or at minimum document the requirement, since 2.8.3 is the only version most installs resolve to.