abhigyanpatwari/GitNexus · error · OSError

short write while copying task assets

Error message

short write while copying task assets

What it means

Raised by _write_all when os.write returns a value <= 0, i.e. the destination descriptor refused the chunk. It is a plain OSError (not SandboxError) because the failure is an OS-level I/O condition on the temporary destination file, not a sandbox policy violation.

Source

Thrown at eval/workflow_bench/task_assets.py:873

    try:
        fcntl.ioctl(destination_descriptor, FICLONE, source_descriptor)
        return True
    except OSError as exc:
        if exc.errno in _REFLINK_UNAVAILABLE:
            return False
        raise


def _read_source_chunk(descriptor: int, size: int) -> bytes:
    return os.read(descriptor, size)


def _write_all(descriptor: int, data: bytes) -> None:
    view = memoryview(data)
    while view:
        written = os.write(descriptor, view)
        if written <= 0:
            raise OSError("short write while copying task assets")
        view = view[written:]


def _mutation_identity(metadata: os.stat_result) -> tuple[int, int, int, int, int, int]:
    return (
        metadata.st_dev,
        metadata.st_ino,
        metadata.st_mode,
        metadata.st_size,
        metadata.st_mtime_ns,
        metadata.st_ctime_ns,
    )


def _validate_manifest_path(relative: PurePosixPath) -> None:
    try:
        path_bytes = len(relative.as_posix().encode("utf-8"))
    except UnicodeEncodeError as exc:

View on GitHub (pinned to d540b00184)

Solutions

  1. Free space on the destination volume (clone filesystem) and rerun stage_task_assets; the temp file is cleaned up by the os.replace error path.
  2. Raise MAX_BUFFERED_FALLBACK_BYTES only if reflink is genuinely unavailable AND you have confirmed free space exceeds the asset size; otherwise prefer making reflink work.
  3. Ensure the clone target lives on a filesystem with enough free space for the largest sandbox_copy asset (the shipped index is ~290-428 MiB) times the number of concurrent arms.
  4. Verify the destination is not mounted read-only or quota-limited (check df -h and quota -v for the clone path).

Example fix

# before: clone on a 1 GiB tmpfs with a 428 MiB index and no reflink
clone = Path('/tmp/clone')   # tmpfs fills up -> short write

# after: clone on a real volume with headroom, ideally reflink-capable
clone = Path('/var/cache/wfbench/clones/arm1')  # btrfs/xfs, plenty of free space
Defensive patterns

Strategy: validation

Validate before calling

import shutil

def assert_clone_writable(clone: Path, min_free_bytes: int) -> None:
    usage = shutil.disk_usage(clone if clone.exists() else clone.parent)
    if usage.free < min_free_bytes:
        raise RuntimeError(
            f'clone volume has {usage.free} bytes free; need >= {min_free_bytes} '
            f'for buffered asset copy (reflink may be unavailable)'
        )

# Call before stage_task_assets with min_free_bytes >= largest sandbox_copy asset
# (shipped index ~428 MiB) times the number of arms on this volume.

Try / catch

try:
    stage_task_assets(task, repo=repo, clone=clone, snapshot=snapshot)
except OSError as exc:
    if exc.args and 'short write while copying task assets' in str(exc.args[0]):
        # Destination volume is out of space / unwritable. Free space then retry once;
        # do NOT loop — fix the underlying capacity issue first.
        raise RuntimeError('clone volume out of space during asset copy') from exc
    raise

Prevention

When it happens

Trigger: Buffered fallback copy (reflink failed with EXDEV/EINVAL/ENOTTY/EOPNOTSUPP/ENOSYS) writing into the .<name>.<uuid>.tmp file in the clone, and os.write returns <= 0. Typical causes: ENOSPC (disk/quota full), EIO (failing drive), EDQUOT, EPIPE, or the temp filesystem being read-only/remounted.

Common situations: CI runner disk full after materializing a ~290 MiB index multiple times; small tmpfs /tmp quota exhausted; Docker devcontainer with a tiny writable layer; reflink unsupported so every arm pays the full buffered copy and the destination volume fills up.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/bb5d9baadc43e6e0. Report an issue: GitHub.