Skip to content

fix(sandbox): make missing sandbox.mounts host_path a loud ERROR (#3244)#3250

Open
player0718 wants to merge 1 commit into
bytedance:mainfrom
player0718:fix/sandbox-mount-silent-skip-3244
Open

fix(sandbox): make missing sandbox.mounts host_path a loud ERROR (#3244)#3250
player0718 wants to merge 1 commit into
bytedance:mainfrom
player0718:fix/sandbox-mount-silent-skip-3244

Conversation

@player0718
Copy link
Copy Markdown
Contributor

Summary

Refs: #3244

Under make up (docker-compose), LocalSandboxProvider runs inside the
deer-flow-gateway container. sandbox.mounts[].host_path from
config.yaml is resolved against the gateway container's filesystem,
not the host machine — and the container only bind-mounts a fixed
allowlist (config.yaml, extensions_config.json, ../skills,
${DEER_FLOW_HOME}, the docker socket, ~/.claude, ~/.codex).

Any custom host_path from config.yaml is therefore invisible inside
the container, host_path.exists() returns False, and the mount is
silently dropped with only a WARNING log. The same config.yaml works
under make dev (the provider runs on the host directly) but breaks
under make up, leaving agents reading an empty directory in
production with no actionable signal to operators.

The reporter listed three remediations ("至少满足下面一条"). This PR
implements option 1: loud failure. Options 2 (docker-aware mount
auto-translation) and 3 (rename host_path) are intentionally left for
follow-up — they involve breaking config schema or deployment
architecture changes that don't belong in a small DX-fix PR. Option 1
unblocks affected operators today and does not preclude either follow-up.

Changes

File Change
backend/packages/harness/deerflow/sandbox/local/local_sandbox_provider.py logger.warninglogger.error with explicit Docker / docker-compose.yaml / services.gateway.volumes guidance. Skip behaviour preserved (no exception raised) to avoid breaking existing deployments.
backend/packages/harness/deerflow/config/sandbox_config.py Rewrite the misleading \"Path on the host machine\" description on VolumeMountConfig.host_path so it documents reality for both providers: LocalSandboxProvider resolves from the gateway-process filesystem (host in make dev, container in make up); AioSandboxProvider (DooD) passes the value to docker -v and the host Docker daemon resolves it.
config.example.yaml Add a Note: block on the sandbox.mounts template pointing operators at the docker-compose bind-mount requirement and referencing #3244, so the Docker-mode gotcha is discoverable from the canonical template.
backend/tests/test_local_sandbox_provider_mounts.py New regression test test_setup_path_mappings_logs_actionable_error_for_missing_host_path: confirms missing host_path is still skipped (no behaviour break), asserts an ERROR record is emitted referencing the offending paths, asserts the message contains actionable docker / gateway / docker-compose keywords.

Diff stats: 4 files, +86 / −5.

Test plan

  • cd backend && uv run pytest tests/test_local_sandbox_provider_mounts.py -v — 45 passed (including the new regression).
  • Regression test verified as a true regression: stashing only the production-code change (keeping the test) makes it fail with AssertionError: expected an ERROR log when host_path is missing.
  • cd backend && uvx ruff check . — All checks passed.
  • cd backend && uv run pytest tests/ (full suite) — 3652 passed / 16 skipped / 1 flake (test_runtime_lifecycle_e2e.py::test_cancel_interrupt_stops_running_background_run, statistically the same race condition on origin/main: 3 fails / 20 runs vs. 1 fail / 20 runs on this branch — unrelated to this PR).
  • Manual end-to-end under make dev (real uvicorn + real HTTP upload triggering lazy get_sandbox_provider()): ERROR appears in uvicorn stderr exactly as designed; pre-fix only emits the buried WARNING.
  • Manual end-to-end under make up (full frontend + gateway + nginx production stack built from the actual backend/Dockerfile): host directory exists on host but not inside the gateway container; upload triggers get_sandbox_provider(); the new ERROR appears in docker compose logs gateway with the actionable guidance referring to services.gateway.volumes in docker/docker-compose.yaml — which I verified matches the real file (service name gateway at L64, volumes block at L75).

Compatibility & scope

  • No runtime behaviour change for working deployments — missing host_path is still skipped, just loudly.
  • Field rename and config schema are untouched.
  • Does not modify _get_custom_mounts in backend/packages/harness/deerflow/sandbox/tools.py (second-pass filter on the same config). The provider-side ERROR already surfaces the problem; adding a second logger there would mean introducing a logging import in a file that has none today.
  • AIO path (community/aio_sandbox/local_backend.py) was reviewed and is intentionally out of scope: it passes host_path directly to docker -v, so the docker daemon resolves it from the host's perspective. The new host_path description now covers this case explicitly so AIO users aren't misled.

Happy to drop the explanatory block comment inside _setup_path_mappings() or trim the docstring further if maintainers prefer a tighter footprint.

…edance#3244)

In Docker production deployments, LocalSandboxProvider runs inside the
deer-flow-gateway container, so any `sandbox.mounts[].host_path` from
config.yaml is resolved against the gateway container's filesystem — not
the host machine. When the path isn't also bind-mounted into the gateway
service, the mount was silently dropped with only a WARNING log, leaving
agents reading an empty directory in production while the same config
worked under `make dev`.

Escalate the missing-host_path branch to logger.error with explicit
guidance about Docker bind mounts and docker-compose, so the failure is
hard to miss in default log configurations. Skip behaviour is preserved
to avoid breaking existing deployments.

Also clarify the misleading `VolumeMountConfig.host_path` field
description so it documents reality for both providers:

  - LocalSandboxProvider checks host_path from inside the gateway process
    (host in `make dev`, container in `make up`).
  - AioSandboxProvider (DooD) passes host_path straight to `docker -v`
    for the sandbox container, where the host Docker daemon resolves it
    from the host machine's perspective.

config.example.yaml's `sandbox.mounts` comment gets a Note: block
pointing operators at the docker-compose bind-mount requirement so the
Docker-mode gotcha is discoverable from the canonical template.

Adds a regression test that:
  - confirms missing host_path is still skipped (no behaviour break);
  - asserts an ERROR record is emitted referencing the offending paths;
  - asserts the message contains actionable Docker/gateway/docker-compose
    keywords so future refactors can't quietly downgrade it.

Refs: bytedance#3244
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


jingkang50 seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes missing sandbox.mounts[].host_path entries more visible for LocalSandboxProvider, addressing Docker production-mode confusion where paths may not exist inside the gateway container.

Changes:

  • Escalates missing custom mount paths from warning to actionable error logs.
  • Clarifies host_path semantics for Local vs AIO sandbox providers.
  • Adds example config guidance and regression coverage for the new logging behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
backend/packages/harness/deerflow/sandbox/local/local_sandbox_provider.py Logs missing custom mount paths as actionable errors while preserving skip behavior.
backend/packages/harness/deerflow/config/sandbox_config.py Updates host_path field description to document provider-specific resolution semantics.
config.example.yaml Adds Docker-mode guidance for custom sandbox mounts.
backend/tests/test_local_sandbox_provider_mounts.py Adds regression coverage for missing-host-path error logging and preserved skip behavior.

@WillemJiang
Copy link
Copy Markdown
Collaborator

@player0718 Please update your GitHub profile with the git committer author email to address the complaint of the CLA assistant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants