bytedance/deer-flow · error · HTTPException

Failed to update memory fact.

Error message

Failed to update memory fact.

What it means

Raised as HTTP 500 by PATCH /memory/facts/{fact_id} when manager.update_fact fails with an OSError while writing the updated store. Distinct from 404 (fact missing), 4xx validation (ValueError), and conflict/corruption errors which are mapped separately.

Source

Thrown at backend/app/gateway/routers/memory.py:390

    try:
        memory_data = await asyncio.to_thread(
            manager.update_fact,
            fact_id=fact_id,
            content=request.content,
            category=request.category,
            confidence=request.confidence,
            user_id=_resolve_memory_user_id(http_request),
        )
    except NotImplementedError:
        raise _unsupported_501(manager, "update fact") from None
    except ValueError as exc:
        raise _map_memory_fact_value_error(exc) from exc
    except KeyError as exc:
        raise HTTPException(status_code=404, detail=f"Memory fact '{fact_id}' not found.") from exc
    except (MemoryConflictError, MemoryCorruptionError) as exc:
        raise _map_memory_manager_error(exc) from exc
    except OSError as exc:
        raise HTTPException(status_code=500, detail="Failed to update memory fact.") from exc

    return MemoryResponse(**memory_data)


@router.get(
    "/memory/export",
    response_model=MemoryResponse,
    response_model_exclude_none=True,
    summary="Export Memory Data",
    description="Export the current global memory data as JSON for backup or transfer.",
)
async def export_memory(http_request: Request) -> MemoryResponse:
    """Export the current memory data."""
    manager = await asyncio.to_thread(get_memory_manager)
    memory_data = await _get_memory_or_501(manager, _resolve_memory_user_id(http_request), "export memory")
    return MemoryResponse(**memory_data)

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Inspect the chained OSError in Gateway logs for the failing path and errno.
  2. Fix filesystem permissions/ownership on the memory store directory and ensure it is mounted read-write.
  3. Free disk space or raise the volume size quota.
  4. Route each Gateway instance to its own memory store path if replicas run concurrently.
Defensive patterns

Strategy: retry

Validate before calling

assert os.access(MEMORY_STORE_DIR, os.W_OK), "memory store not writable before patch"

Try / catch

resp = requests.patch(f"{BASE}/api/memory/facts/{fact_id}", json=patch)
if resp.status_code == 500 and "Failed to update" in resp.json().get("detail", ""):
    retry_with_backoff(max_attempts=3)  # transient filesystem failure
elif resp.status_code == 404:
    handle_missing_fact(fact_id)
elif resp.status_code == 409:
    handle_conflict(resp)

Prevention

When it happens

Trigger: PATCH /api/memory/facts/{fact_id} with a valid body while the memory backend cannot persist changes: read-only mount, disk full, or file lock contention.

Common situations: Read-only Docker volume for the memory store; SELinux denying writes; multiple Gateway replicas sharing one store path without coordination.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/f90447c61780d4fe. Report an issue: GitHub.