bytedance/deer-flow · error · HTTPException
Failed to delete local thread data.
Error message
Failed to delete local thread data.
What it means
Raised by DELETE /threads/{thread_id} when deleting the thread's on-disk data directory raises an unexpected exception (anything other than ValueError, which maps to 422, or FileNotFoundError, which is treated as success). The endpoint delegates to path_manager.delete_thread_dir(thread_id, user_id=user_id); an OSError from the filesystem surfaces here as a 500. The full traceback is logged via logger.exception before the HTTPException is raised.
Source
Thrown at backend/app/gateway/routers/threads.py:541
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _delete_thread_data(thread_id: str, paths: Paths | None = None, *, user_id: str | None = None) -> ThreadDeleteResponse:
"""Delete local persisted filesystem data for a thread."""
path_manager = paths or get_paths()
try:
path_manager.delete_thread_dir(thread_id, user_id=user_id)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
except FileNotFoundError:
# Not critical — thread data may not exist on disk
logger.debug("No local thread data to delete for %s", sanitize_log_param(thread_id))
return ThreadDeleteResponse(success=True, message=f"No local data for {thread_id}")
except Exception as exc:
logger.exception("Failed to delete thread data for %s", sanitize_log_param(thread_id))
raise HTTPException(status_code=500, detail="Failed to delete local thread data.") from exc
logger.info("Deleted local thread data for %s", sanitize_log_param(thread_id))
return ThreadDeleteResponse(success=True, message=f"Deleted local thread data for {thread_id}")
async def _fetch_raw_pending_writes(checkpointer: Any, config: dict[str, Any]) -> list[Any]:
"""Fetch pending writes attached to a specific checkpoint.
Snapshot ``tasks`` only reflect writes that were pending while a task was
still scheduled; writes attached to the latest checkpoint afterwards
(rollback reattachment, worker error fallback) never surface there, so the
status derivation needs one raw tuple fetch on the resolved checkpoint.
"""
raw_tuple = await checkpointer.aget_tuple(config)
if raw_tuple is None:
return []
return list(getattr(raw_tuple, "pending_writes", ()) or ())
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Check the Gateway logs for the logger.exception('Failed to delete thread data for %s') traceback — it names the exact OSError and path class involved.
- Verify the Gateway process user owns or can write the configured thread data root (check config.yaml persistence paths) — fix ownership with chown -R on the data dir.
- Retry the DELETE once transient filesystem conditions (lock, mount flap) clear; confirm no other process (backup job, another Gateway replica) is traversing the dir.
- If it recurs on a specific thread, inspect that thread's directory manually and remove it by hand, then re-issue the DELETE (FileNotFoundError path then returns success).
Defensive patterns
Strategy: try-catch
Try / catch
try {
await fetch(`/api/threads/${id}`, {method: 'DELETE'});
} catch (e) {
// network-level failure only; HTTP 500 arrives as a normal response
}
// on 500: surface 'deletion failed, retry' and keep the thread in the list; on 404/200 remove it Prevention
- Keep the Gateway process as the owner of its data directory; avoid chown-ing it to other users.
- Don't run backup/antivirus jobs that traverse thread data dirs while the Gateway serves deletes.
- Treat DELETE as retryable: re-issue on 500, since FileNotFoundError is already handled server-side as success.
When it happens
Trigger: DELETE /api/threads/{thread_id} while the data directory or files inside it are unreadable/unwritable (PermissionError, EACCES), a path component was replaced by a file, the disk is full or read-only, or an external process holds/locks files during deletion on Windows-style mounts.
Common situations: Data dir created by root in a container then served by a non-root user; volume permission drift after chown/chmod; NFS/FUSE mounts returning EIO; concurrent deletion races where a rmtree partially fails after FileNotFoundError of an inner entry was handled but other inner errors are not.
Related errors
- Failed to update user profile: {str(e)}
- Failed to delete agent: {str(e)}
- Failed to clear memory data.
- Failed to delete {filename}: {str(e)}
- Failed to delete local thread data.
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/07e6eeee5cdf3982.
Report an issue: GitHub.