bytedance/deer-flow · error · HTTPException
Failed to acquire sandbox
Error message
Failed to acquire sandbox
What it means
HTTP 500 raised when the sandbox provider reports success from acquire_async(thread_id) but get(sandbox_id) then returns None — an internal inconsistency between the provider's acquire and get APIs. It means the gateway cannot obtain the sandbox handle needed to sync uploaded files into the thread's sandbox.
Source
Thrown at backend/app/gateway/routers/uploads.py:339
sandbox_uploads = uploads_dir
uploaded_files = []
written_paths = []
sandbox_sync_targets = []
skipped_files = []
total_size = 0
# Track filenames within this request so duplicate form parts do not
# silently truncate each other. Existing uploads keep the historical
# overwrite behavior for a single replacement upload.
seen_filenames: set[str] = set()
sandbox_provider = get_sandbox_provider()
sync_to_sandbox = not _uses_thread_data_mounts(sandbox_provider)
sandbox = None
if sync_to_sandbox:
sandbox_id = await sandbox_provider.acquire_async(thread_id, user_id=effective_user_id)
sandbox = sandbox_provider.get(sandbox_id)
if sandbox is None:
raise HTTPException(status_code=500, detail="Failed to acquire sandbox")
auto_convert_documents = _auto_convert_documents_enabled(config)
for file in files:
if not file.filename:
continue
try:
original_filename = normalize_filename(file.filename)
safe_filename = claim_unique_filename(original_filename, seen_filenames)
except ValueError:
logger.warning(f"Skipping file with unsafe filename: {file.filename!r}")
continue
try:
file_path, file_size, total_size = await _write_upload_file_with_limits(
file,
uploads_dir=uploads_dir,
display_filename=safe_filename,View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Retry the upload once — transient races between acquire and get often clear.
- Check sandbox provider logs/health (container runtime, provisioner on port 8002 if configured) for crashes or evictions.
- If running a custom sandbox provider, ensure acquire_async registers the sandbox so a subsequent get(sandbox_id) succeeds.
- As a workaround, switch the deployment to a sandbox provider that uses thread data mounts (sync_to_sandbox becomes false and this path is skipped).
Defensive patterns
Strategy: retry
Try / catch
catch 500 with detail 'Failed to acquire sandbox'; retry the upload once after a short delay; escalate to the operator if it repeats.
Prevention
- Monitor sandbox provider health (container runtime / provisioner) alongside the gateway.
- Prefer sandbox providers using thread data mounts, which skip the acquire/sync path entirely.
- Keep sandbox registry TTLs comfortably longer than the longest upload request.
When it happens
Trigger: Only on deployments whose sandbox provider uses file syncing (i.e. _uses_thread_data_mounts is false): acquire_async returns an id, but the corresponding sandbox record is missing/expired by the time get() is called.
Common situations: Sandbox registry TTL expiring between acquire and get; a custom sandbox provider with a bug where acquire does not register the sandbox; sandbox backend (container/K8s) crash or eviction mid-request.
Related errors
- Failed to update artifact
- Failed to complete Lark authorization.
- Failed to upload {file.filename}: {str(e)}
- Failed to delete {filename}: {str(e)}
- Failed to prepare ${failedConversions} attachment(s) for upl
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/2afb7fe3692787ec.
Report an issue: GitHub.