agentscope-ai / agentscope-ai/agentscope-java

[harness][sandbox] SandboxBackedFilesystem.uploadFiles fails with CreateProcess error=206 / E2BIG because file content is base64-embedded into the docker exec command line

Abierto
#1,560 2 comentarios 1 reacción 0 asignados Ver en GitHub
area/harness bug
Lenguaje dominante
Java
Estrellas
5.6k
Forks
1.3k
Merge medio
4 d 12 h
PR fusionados (30 d)
77

Descripción

## Summary

`SandboxBackedFilesystem.uploadFiles(...)` mirrors files into the Docker sandbox by **base64-encoding the whole file content and embedding it as a single argument of a `docker exec sh -c "..."` command line**. When the file is large enough (e.g. an accumulated session history `.jsonl`), the resulting command line exceeds the OS single-argument / command-line length limit and the process fails to start:

- **Windows**: `java.io.IOException: CreateProcess error=206, The filename or extension is too long` (command line limit ~32 KB).
- **Linux**: same root cause, fails with `E2BIG` once a single arg exceeds `MAX_ARG_STRLEN` (~128 KB). Higher threshold, so much rarer, but not immune.

This breaks the asynchronous session-log mirroring (`SessionTree.scheduleMirror` → `mirrorToFilesystem` → `uploadFiles`) during normal conversations once the session log grows.

## Affected version

- `agentscope-harness:1.1.0-SNAPSHOT`

## Root cause (source)

`io.agentscope.harness.agent.filesystem.sandbox.SandboxBackedFilesystem#uploadFiles`:

```java
String base64Content = Base64.getEncoder().encodeToString(content); // full file content
String escapedPath = shellSingleQuote(path);
String cmd =
"mkdir -p $(dirname " + escapedPath + ") && "
+ "printf '%s' '" + base64Content + "' | base64 -d > " + escapedPath;
ExecResult result = active.exec(runtimeContext, cmd, null);
```

This `cmd` (containing the entire base64 blob, which is ~1.33x the original size) is then passed to `io.agentscope.harness.agent.sandbox.impl.docker.DockerSandbox#doExec`, which puts it verbatim as the last argument:

```java
List cmd = new ArrayList<>();
cmd.add("docker"); cmd.add("exec");
cmd.add("-w"); cmd.add(workspaceRoot);
cmd.add(containerId);
cmd.add("sh"); cmd.add("-c");
cmd.add(command); // <-- entire base64 blob ends up on the command line
ProcessBuilder pb = new ProcessBuilder(cmd);
Process process = pb.start(); // throws CreateProcess error=206 on Windows / E2BIG on Linux
```

So the maximum file size is bounded by the **OS command-line length limit**, not by the sandbox.

## Stack trace (Windows)

```
[sandbox-fs] uploadFiles failed for path: agents//sessions/main-.jsonl
java.io.IOException: Cannot run program "docker": CreateProcess error=206, The filename or extension is too long.
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
at io.agentscope.harness.agent.sandbox.impl.docker.DockerSandbox.doExec(DockerSandbox.java:152)
at io.agentscope.harness.agent.sandbox.AbstractBaseSandbox.exec(AbstractBaseSandbox.java:176)
at io.agentscope.harness.agent.filesystem.sandbox.SandboxBackedFilesystem.uploadFiles(SandboxBackedFilesystem.java:113)
at io.agentscope.harness.agent.memory.session.SessionTree.mirrorToFilesystem(SessionTree.java:585)
at io.agentscope.harness.agent.memory.session.SessionTree.lambda$scheduleMirror$4(SessionTree.java:466)
Caused by: java.io.IOException: CreateProcess error=206, The filename or extension is too long.
```

## Steps to reproduce

1. Build a `HarnessAgent` with the Docker sandbox filesystem (`IsolationScope.USER`) on a **Windows** host with Docker Desktop.
2. Hold a multi-turn conversation so the agent's session history (`sessions/main-*.jsonl`) grows beyond ~32 KB.
3. On the next session mirror, `uploadFiles` builds a `docker exec sh -c "...base64..."` command line that exceeds the Windows limit → `CreateProcess error=206`.

(On Linux the same happens once a single mirrored file exceeds ~96 KB raw / ~128 KB base64.)

## Impact

- Conversation and in-container tool execution still work; only the **asynchronous session-log mirroring** to the container fails repeatedly, producing noisy WARN logs.
- On Windows it triggers very quickly (low ~32 KB limit), effectively making the Docker sandbox filesystem unusable for normal-length conversations there.

## Suggested fix

Avoid putting file bytes on the command line. The same class already does this correctly for workspace transfer in `DockerSandbox#doHydrateWorkspace`, which **pipes a tar archive through `docker exec -i ... tar -xf -` via stdin**:

```java
ProcessBuilder pb = new ProcessBuilder("docker","exec","-i",containerId,"tar","-xf","-","-C",dir);
// archive bytes are written to process stdin, NOT the command line
```

`uploadFiles` should use the same stdin-pipe approach (e.g. `docker exec -i sh -c 'cat > '`, or tar via stdin), so file size is bounded by stream throughput rather than the OS command-line limit. This makes it platform-independent and removes the Windows ~32 KB ceiling.

## Environment

- OS: Windows (also affects Linux for large files)
- Java: 17
- Docker: Docker Desktop
- agentscope-harness: 1.1.0-SNAPSHOT

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.