Skip to content

fix(kb): keep the filename and mark a source whose document was deleted - #784

Merged
ViaJables merged 2 commits into
mainfrom
fix/kb-deleted-document-source
Aug 31, 2026
Merged

fix(kb): keep the filename and mark a source whose document was deleted#784
ViaJables merged 2 commits into
mainfrom
fix/kb-deleted-document-source

Conversation

@ViaJables

Copy link
Copy Markdown
Collaborator

Ticket

Deleting a document from Files leaves its knowledge base source in place: the KB stays Ready, still answers from the deleted document's content, and cites it by name and page. The only sign anything changed is that the source is now listed as 12423A16EF3F476BA92B57F5301C2EFF instead of its filename. Extraction test cases already handle this — filename kept, "source deleted" label, an explanation that validation still runs from the saved text.

Cause

KnowledgeBaseSource stores no name for a document source; resolve_document_titles looks the title up live from SmartDocument on every request. Delete the document and the lookup returns nothing, so KnowledgePanel falls through to source.document_title || source.document_uuid — the UUID. Nothing anywhere reported that the document was gone.

The content survives because it lives in ChromaDB, written at ingest and never keyed to the document's continued existence.

Scope decision

Following the ticket's Expected — parity with extraction — the chunks stay and the KB keeps answering. That is the same contract extraction states ("validation still works from the saved text"), and silently emptying knowledge bases when a file is tidied out of Files would be a much larger behavioural change than this report asks for. What changes is that the KB now says the document is gone. Happy to take the other direction (purge chunks on delete) as a follow-up if that's what you want — it's a different conversation about data lifecycle, not a bug fix.

Change

The name survives the documentKnowledgeBaseSource.document_title, written by both ingest paths (kb_ingest_document, kb_reingest) alongside chunk count and status. resolve_document_titles prefers the live title and falls back to it.

The deleted state is reported — new resolve_existing_documents and document_exists on KBSourceResponse (KB detail, source detail, source PATCH). A lookup failure returns "exists" for everything rather than painting every source with a red label.

The UI says soKnowledgePanel renders Award Letter.pdf · source deleted in amber, tooltip: "The source document was deleted from Files. This knowledge base still answers from the text it indexed." KBSourceInspectorModal says the same in its subtitle and drops the Text/File toggle, whose File view could only ever render a 404 for a document that no longer exists.

Two paths already behaved correctly and are untouched: chat citations keep the filename (it comes from chunk metadata, written at ingest), and resolve_openable_documents already withholds the "open the document" affordance when the document is gone, so no citation offers a dead click.

Existing databackend/scripts/backfill_kb_source_titles.py (--dry-run supported). Fills document_title from the live document where there still is one; where there isn't — the rows already broken on prod, including the one in this report — it recovers the name from source_name on the source's own chunks in ChromaDB, which outlive the document. Idempotent, read-only against Chroma, and it handles the implicit-KB chunk-id convention (document_uuid vs source uuid).

Tests

backend/tests/test_kb_deleted_document_source.py (new, 7) — title falls back to the stored one, live title wins, nothing invented when neither exists; existence lookup reports only surviving documents and fails safe; the detail endpoint reports document_exists both ways while keeping the filename.

frontend/.../KnowledgePanel.test.tsx — the deleted source renders its filename and "source deleted" and never the UUID; a live source says nothing about deletion.

test_knowledge_routes.py's two source mocks gained document_title — without it a MagicMock attribute reached a str field on the response model.

Backend: 7 new + test_knowledge_routes.py (92) + four test_kb_source_* suites and test_kb_retrieval.py (113) pass; ruff clean. Frontend: KnowledgePanel.test.tsx (12) passes; tsc --noEmit clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_017f65pmoEKbpBGownseoHf7

ViaJables and others added 2 commits August 31, 2026 12:43
A KB source's display name was resolved live from SmartDocument, so deleting
the document from Files left the row showing a bare UUID with no explanation
— while the KB kept answering from the chunks it had already indexed. The
user saw a confident answer citing a file that no longer exists, and a source
list that named nothing.

Capture the document's title on the source at ingest, so the name survives
the document, and report document_exists on the source response. The KB panel
then shows "Award Letter.pdf · source deleted" with a tooltip saying answers
still come from the indexed text — the treatment extraction test cases
already get. The inspector says the same and drops its File tab, which could
only ever render a 404 for a deleted document.

Adds scripts/backfill_kb_source_titles.py for rows ingested before this: it
fills the title from the live document where there still is one, and from the
source_name on the source's own chunks where there isn't — the chunks outlive
the document and carry the name it had when indexed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f65pmoEKbpBGownseoHf7
# Conflicts:
#	frontend/src/components/workspace/KnowledgePanel.test.tsx
@ViaJables
ViaJables merged commit 13132bf into main Aug 31, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant