Skip to content

[Bug]: BaseSandboxFilesystem.edit fails when replaceAll=false because the generated Python command contains literal \\n sequences` #2571

Closed

Description

@HuJiShuang

Describe the bug**

BaseSandboxFilesystem.edit(..., replaceAll=false) fails before reading or modifying the target file. The generated python3 -c program contains literal \\n character sequences instead of actual newline characters. On a POSIX shell, \\n inside a double-quoted argument is passed to Python unchanged, so Python raises a SyntaxError.

This affects the default single-replacement path used by the edit_file tool. The file is left unchanged.

The bug is present in AgentScope-Java 2.0.0 and is still present on main at commit 9b77823678b4ae919f7c14bc10fb7560879979d7 (2.0.1-SNAPSHOT).

To Reproduce

  1. Use a sandbox-backed filesystem whose execute implementation runs commands through a POSIX shell and provides python3.

  2. Create a file such as /tmp/example.txt containing old.

  3. Invoke the filesystem edit operation with replaceAll=false, for example through the tool:

    edit_file({"path":"/tmp/example.txt","old_string":"old","new_string":"new"})
    
  4. Observe that the operation fails with a Python syntax error and /tmp/example.txt is unchanged.

The generated command starts with:

python3 -c "import sys, os, base64, json\npayload = ..."

A minimal shell-level reproduction is:

python3 -c "import sys, os, base64, json\npayload = {}"

Expected behavior

The first occurrence of old_string should be replaced with new_string, and the edit operation should return a successful EditResult.

Error messages

Error editing file '/tmp/example.txt': unexpected server response: File "<string>", line 1
    import sys, os, base64, json\npayload = json.loads(...)
                                  ^
SyntaxError: unexpected character after line continuation character

Environment (please complete the following information):

  • AgentScope-Java Version: 2.0.0; also reproducible from main at 9b77823678b4ae919f7c14bc10fb7560879979d7 (2.0.1-SNAPSHOT)
  • Java Version: OpenJDK 21.0.12
  • OS: macOS 26.3.2 arm64 host; POSIX sandbox shell with Python 3

Additional context

The command is constructed in:

agentscope-harness/src/main/java/io/agentscope/harness/agent/filesystem/sandbox/BaseSandboxFilesystem.java

The Python source lines are currently joined using Java string fragments ending in \\n, for example:

"python3 -c \"import sys, os, base64, json\\n"

This produces a backslash followed by n at runtime, not a line feed. POSIX shells do not translate \\n inside double quotes. Python then interprets the backslash as a line-continuation character and rejects the following n.

The returned process exit code is also not checked before parsing stdout. Because the syntax-error output contains neither the expected "error" nor "count" JSON field, it is reported as unexpected server response, which hides the actual command-execution failure.

Possible fixes:

  1. Use actual newline characters (\n in the Java source) when building the Python program, or pass the Python program through a quoted heredoc and pass the Base64 payload as an argument.
  2. Check a non-zero execution exit code before parsing the expected JSON response.
  3. Add a real-shell integration test for edit(..., replaceAll=false) that verifies the file contents.

Activity

  1. moved this from Backlog to In progress in AgentScope Javaon Aug 11, 2026
  2. aiyili commented on Sep 21, 2026

    @aiyili
    Contributor

    Hi, I'd like to work on this issue. I've prepared a fix that:

    1. Builds the python3 -c program with a Java text block so its statements are separated by real line feeds — inside a POSIX double-quoted string the literal two-character sequence reaches python3 unchanged, which collapses the program into a single line and fails with SyntaxError (verified against a real sh + python3: the old command fails, the fixed command performs the replacement).
    2. Checks the process exit code before parsing the expected JSON response, so execution-layer failures (timeout / transport error / interpreter crash) surface with their cause instead of unexpected server response.
    3. Adds unit tests (generated command shape + canned failure responses) and Linux real-shell integration tests for edit(..., replaceAll=false) (single replacement, multiple-occurrence refusal, replaceAll).

    PR coming shortly.

  3. added a commit that references this issue on Sep 21, 2026
    7867333
  4. oss-maintainer commented on Sep 21, 2026

    @oss-maintainer
    Collaborator

    Issue Evaluation

    Category: bug | Status: Confirmed (checked against main @ c0d03ccea)

    The reported defect is real and still present. Code-engine verification:

    Reporter claim Verdict
    Generated python3 -c program uses literal \n (backslash + n) instead of real newlines Confirmed — agentscope-harness/src/main/java/io/agentscope/harness/agent/filesystem/sandbox/BaseSandboxFilesystem.java:258-281
    Hit on the default replaceAll=false path of edit_file Confirmed — FilesystemTool.java:166 defaults replaceAll=false. Additional finding: the replaceAll=true branch builds the exact same command shape, so both branches are affected, not only the default one
    Failure occurs before the file is read or modified Confirmed — the SyntaxError is raised while Python parses -c, before sys.stdin.read() / open()
    Still present on current main Confirmed

    Why it fails: the Java source terminates each Python statement with \\n, which at runtime is the two-character literal \n. Inside shell double quotes a backslash before n is not an escape, so Python receives the whole program as one physical line and aborts at parse time.

    Blast radius: SandboxBackedFilesystem and SharedSandboxFilesystem extend BaseSandboxFilesystem and do not override edit(...), so every sandbox-backed filesystem shares the defect — the edit_file tool path is broken there. Severity: high.

    Test gap: BaseSandboxFilesystemTest has no edit coverage, and FilesystemToolTest mocks the filesystem layer, so the generated command string is never executed or asserted. Any fix should pin the command construction (real line feeds present, base64 heredoc payload intact) so this cannot regress.

    On fix work: two community PRs already target this issue — #2573 and #3226. To avoid duplicate competing work, no automated fix proposal will be generated from this evaluation; the maintainer review queue on those PRs is where this should land. Reviewers may want the extra replaceAll=true finding and the regression-test point above.


    Automated evaluation by github-manager (oss-maintainer)

  5. added a commit that references this issue on Sep 21, 2026
    8adb544
  6. added a commit that references this issue on Sep 28, 2026
    5257062
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/examplesagentscope-examplesarea/extensionsagentscope-extensions (general)bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions