bytedance/deer-flow · warning · HTTPException

Binary artifacts cannot be edited

Error message

Binary artifacts cannot be edited

What it means

HTTP 415 from _load_editable_artifact: the artifact's bytes contain a NUL byte (b'\x00'), the heuristic for binary content. The panel editor is text-only; round-tripping binary through a JSON string field would corrupt it, so such artifacts are refused for editing.

Source

Thrown at backend/app/gateway/routers/artifacts.py:93


def _load_editable_artifact(actual_path: Path, path: str, expected_sha256: str) -> tuple[bytes, os.stat_result]:
    try:
        file_stat = os.lstat(actual_path)
    except FileNotFoundError:
        raise HTTPException(status_code=404, detail=f"Artifact not found: {path}") from None
    if stat.S_ISLNK(file_stat.st_mode):
        raise HTTPException(status_code=415, detail="Symlinked artifacts cannot be edited")
    if not stat.S_ISREG(file_stat.st_mode):
        raise HTTPException(status_code=400, detail=f"Path is not a file: {path}")
    if file_stat.st_size > MAX_EDITABLE_ARTIFACT_BYTES:
        raise HTTPException(status_code=413, detail="Artifact is too large to edit")

    current = actual_path.read_bytes()
    if len(current) > MAX_EDITABLE_ARTIFACT_BYTES:
        raise HTTPException(status_code=413, detail="Artifact is too large to edit")
    if b"\x00" in current:
        raise HTTPException(status_code=415, detail="Binary artifacts cannot be edited")
    try:
        current.decode("utf-8")
    except UnicodeDecodeError:
        raise HTTPException(status_code=415, detail="Only UTF-8 text artifacts can be edited") from None

    current_sha256 = hashlib.sha256(current).hexdigest()
    if current_sha256 != expected_sha256:
        raise HTTPException(status_code=412, detail="Artifact changed since it was opened")
    return current, file_stat


def _encode_artifact_update(content: str) -> bytes:
    encoded = content.encode("utf-8")
    if len(encoded) > MAX_EDITABLE_ARTIFACT_BYTES:
        raise HTTPException(status_code=413, detail="Artifact is too large to edit")
    if b"\x00" in encoded:
        raise HTTPException(status_code=415, detail="Binary content cannot be saved as an artifact")
    return encoded

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Use the preview/download path (GET artifact) instead of the edit path for binary files
  2. Convert the artifact to UTF-8 text before offering edit (e.g. export CSV instead of XLSX)
  3. If UTF-16 was intended, re-encode as UTF-8 — UTF-16 files always contain NULs and are rejected by design
Defensive patterns

Strategy: validation

Validate before calling

def looks_editable_text(data: bytes) -> bool:
    return b"\x00" not in data

Type guard

def is_editable_text_bytes(data: bytes) -> bool:
    """Mirrors the Gateway's binary heuristic."""
    if b"\x00" in data:
        return False
    try:
        data.decode("utf-8")
        return True
    except UnicodeDecodeError:
        return False

Try / catch

if resp.status_code == 415 and "Binary" in resp.text:
    show_binary_preview_or_download(path)

Prevention

When it happens

Trigger: PUT edit-artifact (open/save) on any outputs file containing NUL bytes: images, serialized objects, databases, some PDFs/office formats even when MIME-sniffed as text.

Common situations: Users clicking Edit on generated binaries whose extension suggested text, agents writing pickle/parquet/sqlite outputs, UTF-16 files (NUL-heavy) produced on other platforms.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/bcd275cc4c6a3783. Report an issue: GitHub.