infiniflow/ragflow · error · NotFoundException
NOT_FOUND
NOT_FOUND
Error message
Memory '{memory_id}' not found. What it means
Raised by _require_memory_access when MemoryService.get_by_memory_id returns no row, or when the row exists but the caller is not allowed to see it (not the owner, and either the memory is not TEAM-permission or the caller has not joined that tenant). Deliberately a single NotFound error for both 'missing' and 'forbidden' to avoid leaking existence of other tenants' memories.
Source
Thrown at api/apps/services/memory_api_service.py:67
def _joined_tenant_ids(user_id: str) -> set[str]:
user_tenants = UserTenantService.get_user_tenant_relation_by_user_id(user_id)
return {user_id, *[tenant["tenant_id"] for tenant in user_tenants]}
def _memory_accessible(memory) -> bool:
if memory.tenant_id == current_user.id:
return True
if memory.permissions != TenantPermission.TEAM.value:
return False
return memory.tenant_id in _joined_tenant_ids(current_user.id)
def _require_memory_access(memory_id: str):
memory = MemoryService.get_by_memory_id(memory_id)
if not memory or not _memory_accessible(memory):
raise NotFoundException(f"Memory '{memory_id}' not found.")
return memory
def _filter_accessible_memories(memory_ids: list[str]):
memory_ids = _split_filter_values(memory_ids)
if not memory_ids:
return []
return [memory for memory in MemoryService.get_by_ids(memory_ids) if _memory_accessible(memory)]
async def create_memory(memory_info: dict):
"""
:param memory_info: {
"name": str,
"memory_type": list[str],
"embd_id": str,
"llm_id": str,
"tenant_embd_id": str | None,View on GitHub (pinned to 554fb1133a)
Solutions
- Re-list memories (GET memory collection) to get fresh, accessible ids and drop cached ones
- If the memory belongs to another user, ask the owner to set permissions=TEAM and have the caller join that tenant
- Verify the id is the exact uuid returned by the create/list API
- Handle 404 as terminal — do not retry; refresh the id source instead
Defensive patterns
Strategy: validation
Validate before calling
import uuid
def valid_memory_id(mid: str) -> bool:
try:
uuid.UUID(mid)
return True
except (ValueError, TypeError):
return False
# also: re-list accessible memories and only use returned ids Type guard
def is_memory_id(v) -> bool:
return isinstance(v, str) and valid_memory_id(v) Try / catch
try:
get_memory(mid)
except NotFoundException:
memories = list_memories() # refresh cache of ids
if mid not in {m["id"] for m in memories}:
drop_cached(mid) # terminal: forget this id Prevention
- Always source memory ids from a fresh list call, never from long-lived caches
- Remember 404 also covers 'exists but not shared with you' — request TEAM permission for cross-user access
- Do not retry 404s; they are deterministic
When it happens
Trigger: GET/PUT/DELETE /api/v1/memory/{memory_id} (or memory-list endpoints filtering by ids) with a wrong/revoked uuid, a memory belonging to another user without TEAM permission, or a team memory from a tenant the caller never joined.
Common situations: Stale memory ids kept client-side after deletion; sharing a memory id across accounts without granting team permission; environment resets (DB wiped) while clients hold old ids; copy-paste typos in ids.
Related errors
- main() must return a value. Use null for an empty result.
- main() returned a non-JSON-serializable value.
- message.compileNotSupported
- Repository or path not found. Please check the URL and ensur
- User '{username}' not found
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/afba1efdf7426849.
Report an issue: GitHub.