Bug Description
When deleting a resource folder via _enqueue_delete_refresh, the system creates a SemanticMsg with recursive=True (the default), causing the entire resource tree to be re-processed — including all unrelated sibling folders. This results in thousands of unnecessary embedding tasks, API rate limiting (429), server health check timeouts, and massive token waste (~400W tokens wasted in one day).
Steps to Reproduce
- Upload a large code repository as a resource (e.g., the OpenViking repo itself with 2874 files)
- Upload another resource folder with ~1000 files
- Delete the second folder
- Observe the embedding task queue
Expected Behavior
Deleting a folder should:
- Update the parent directory's overview to reflect the deletion
- Use existing abstracts for sibling directories (not re-process them)
- Trigger a small number of embedding tasks (only for the parent directory, ~2 tasks)
Actual Behavior
Deleting a folder triggers:
- A
SemanticMsg with uri=viking://resources, recursive=True, changes={'deleted': ['viking://resources/<folder>/']}
- 2874+ embedding tasks for the entire resource tree (including unrelated sibling folders)
- 15,000+ 429 rate limit errors from the VLM API
- Server health check timeouts (container marked
unhealthy)
- ~400W tokens wasted on unnecessary VLM calls for re-processing already-indexed files
Minimal Reproducible Example
# File: openviking/service/fs_service.py:313-345
async def _enqueue_delete_refresh(self, *, root_uri, deleted_uri, context_type, ctx):
msg = SemanticMsg(
uri=root_uri, # viking://resources
context_type=context_type,
changes={"deleted": [deleted_uri]},
# ❌ BUG: No explicit recursive=False
# SemanticMsg defaults to recursive=True
)
await semantic_queue.enqueue(msg)
`SemanticMsg` default:
# File: openviking/storage/queuefs/semantic_msg.py:46
@dataclass
class SemanticMsg:
recursive: bool = True # Default is True!
Error Logs
07:15:14 Processing semantic generation for: SemanticMsg(
uri='viking://resources',
recursive=True,
changes={'deleted': ['viking://resources/<folder>/']}
)
07:19:05 Registered 2874 embedding tasks ← BUG: should be ~2 tasks
07:27:04 2874 tasks completed (8 minutes of unnecessary work)
07:46:17 Server recovers (was unhealthy for ~9 minutes)
OpenViking Version
main
Python Version
3.13
Operating System
Windows
Model Backend
None
Additional Context
Root Cause
_enqueue_delete_refresh (introduced in 2583da84 "Feature/wiki link (#2558)") doesn't set recursive=False. The SemanticMsg default is recursive=True, so the entire resource tree gets re-processed on delete.
Why recursive=False Is Correct
With recursive=False, the SemanticDagExecutor:
- Processes only files in the parent directory itself
- Uses existing abstracts for children directories (via
_finalize_children_abstracts)
- Generates a new overview reflecting the deletion
- Does NOT re-process sibling directories
Related Issues/PRs
Bug Description
When deleting a resource folder via
_enqueue_delete_refresh, the system creates aSemanticMsgwithrecursive=True(the default), causing the entire resource tree to be re-processed — including all unrelated sibling folders. This results in thousands of unnecessary embedding tasks, API rate limiting (429), server health check timeouts, and massive token waste (~400W tokens wasted in one day).Steps to Reproduce
Expected Behavior
Deleting a folder should:
Actual Behavior
Deleting a folder triggers:
SemanticMsgwithuri=viking://resources,recursive=True,changes={'deleted': ['viking://resources/<folder>/']}unhealthy)Minimal Reproducible Example
Error Logs
OpenViking Version
main
Python Version
3.13
Operating System
Windows
Model Backend
None
Additional Context
Root Cause
_enqueue_delete_refresh(introduced in2583da84"Feature/wiki link (#2558)") doesn't setrecursive=False. TheSemanticMsgdefault isrecursive=True, so the entire resource tree gets re-processed on delete.Why
recursive=FalseIs CorrectWith
recursive=False, theSemanticDagExecutor:_finalize_children_abstracts)Related Issues/PRs