crewAIInc/crewAI · error · RuntimeError

append failed: exit_code={exit_code}, output={getattr(respon

Error message

append failed: exit_code={exit_code}, output={getattr(response, 'result', '')!r}

What it means

DaytonaFileTool._append implements append by writing a temp file and running a shell append command via sandbox.process.code_run; if that process returns a non-zero exit_code it raises RuntimeError with the code and captured output. Before raising it best-effort deletes the temp file (failures only logged at debug). Common underlying causes are a missing parent directory, permission denial, or a read-only filesystem inside the sandbox.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py:373

        quoted_temp = shlex.quote(temp_path)
        quoted_target = shlex.quote(path)
        response = sandbox.process.exec(
            f"cat {quoted_temp} >> {quoted_target}; "
            f"rc=$?; rm -f {quoted_temp}; exit $rc"
        )

        exit_code = getattr(response, "exit_code", 0)
        if exit_code != 0:
            try:
                sandbox.fs.delete_file(temp_path)
            except Exception:
                logger.debug(
                    "Best-effort temp-file cleanup failed after append "
                    "error; the file may need manual deletion.",
                    exc_info=True,
                )
            raise RuntimeError(
                f"append failed: exit_code={exit_code}, "
                f"output={getattr(response, 'result', '')!r}"
            )

        try:
            info = sandbox.fs.get_file_info(path)
            total_bytes = getattr(info, "size", None)
        except Exception:
            total_bytes = None

        return {
            "status": "appended",
            "path": path,
            "appended_bytes": len(chunk),
            "total_bytes": total_bytes,
        }

    @staticmethod

View on GitHub (pinned to 754d7323be)

Solutions

  1. Inspect the output= field in the RuntimeError message — it contains the sandbox-side stderr explaining the failure.
  2. Ensure the parent directory exists first: _run(action='mkdir', path=parent) or create the file with action='write' before appending.
  3. Check permissions/free space in the sandbox (action='info' on the path).
  4. Retry once if the output suggests a transient sandbox error; report the full message if it persists.

Example fix

# before (parent dir may not exist)
file_tool._run(action='append', path='/logs/run.log', content='line\n')

# after
file_tool._run(action='mkdir', path='/logs')
file_tool._run(action='append', path='/logs/run.log', content='line\n')
Defensive patterns

Strategy: try-catch

Validate before calling

def append_safe(file_tool, path: str, content: str, *, binary: bool = False):
    parent = path.rsplit('/', 1)[0] or '/'
    if not file_tool._run(action='exists', path=parent).get('exists'):
        file_tool._run(action='mkdir', path=parent)
    return file_tool._run(action='append', path=path, content=content, binary=binary)

Try / catch

try:
    result = file_tool._run(action='append', path=p, content=c)
except RuntimeError as e:
    msg = str(e)
    if 'exit_code=' in msg:
        # msg carries sandbox-side output; create parent dir and retry once
        file_tool._run(action='mkdir', path=p.rsplit('/', 1)[0] or '/')
        result = file_tool._run(action='append', path=p, content=c)
    else:
        raise

Prevention

When it happens

Trigger: _run(action='append', path='/newdir/file.txt', content='x') where /newdir does not exist; appending to a file owned by another user; disk full in the sandbox; the sandbox process API returning a non-zero code for the internal cat/append command.

Common situations: Agents appending logs to a path whose directory was never created (mkdir step skipped); sandboxes with restricted write permissions; transient sandbox process failures surfacing as opaque exit codes.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/737822a7b867c059. Report an issue: GitHub.