abhigyanpatwari/GitNexus · error · SandboxError

transcript artifact metadata must contain only path, sha256,

Error message

transcript artifact metadata must contain only path, sha256, bytes, and source

What it means

_transcript_artifact_metadata pins the admissible schema to exactly four keys: {path, sha256, bytes, source}. Extra keys (e.g. 'mtime', 'mtime_ns') or missing ones mean the row was not produced by the trusted runner, so the harness rejects it rather than guess which fields to trust.

Source

Thrown at eval/workflow_bench/evolve.py:329

    current = root
    for part in relative.parts[:-1]:
        current /= part
        try:
            metadata = current.lstat()
        except OSError as exc:
            raise SandboxError(f"results artifact parent is unavailable: {current}: {exc}") from exc
        if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
            raise SandboxError(f"results artifact parent must be a real directory: {current}")
        if transcript and stat.S_IMODE(metadata.st_mode) & 0o077:
            raise SandboxError(f"transcript artifact parent must be owner-only: {current}")
    return root / Path(*relative.parts)


def _transcript_artifact_metadata(metadata: Any) -> tuple[str, str, int]:
    """Validate transcript metadata without touching any host path."""

    if not isinstance(metadata, dict) or set(metadata) != {"path", "sha256", "bytes", "source"}:
        raise SandboxError("transcript artifact metadata must contain only path, sha256, bytes, and source")
    relative = metadata["path"]
    expected_digest = metadata["sha256"]
    expected_size = metadata["bytes"]
    if metadata["source"] != runner_sessions.PARENT_EVENT_STREAM_SOURCE:
        raise SandboxError("transcript artifact source is not the parent event stream")
    if not isinstance(relative, str) or not re.fullmatch(r"[0-9a-f]{64}", str(expected_digest)):
        raise SandboxError("transcript artifact metadata is malformed")
    if not isinstance(expected_size, int) or isinstance(expected_size, bool):
        raise SandboxError("transcript artifact byte count must be an integer")
    if expected_size < 0 or expected_size > runner.MAX_TRANSCRIPT_BYTES:
        raise SandboxError("transcript artifact exceeds the bounded run-output limit")
    return relative, expected_digest, expected_size


def _normalized_transcript_artifact_path(relative_value: str) -> str:
    """Apply the transcript path contract without touching the filesystem."""

    relative = PurePosixPath(relative_value)

View on GitHub (pinned to d540b00184)

Solutions

  1. Diff the row against the trusted runner's writer (runner_sessions) and align key names exactly.
  2. Regenerate the results row with the current runner so the schema matches.
  3. If adding a field is intended, extend the allowed set in _transcript_artifact_metadata deliberately, with review.

Example fix

# before
{"path": "transcripts/r.json", "sha256": "<64hex>", "bytes": 12, "source": "parent-captured-stream-json", "mtime": 123}

# after (drop the extra key)
{"path": "transcripts/r.json", "sha256": "<64hex>", "bytes": 12, "source": "parent-captured-stream-json"}
Defensive patterns

Strategy: type-guard

Validate before calling

from eval.workflow_bench.evolve import _transcript_artifact_metadata  # reuse the exact check

TRANSCRIPT_KEYS = {"path", "sha256", "bytes", "source"}

def transcript_metadata_shape_ok(metadata: dict) -> bool:
    return isinstance(metadata, dict) and set(metadata) == TRANSCRIPT_KEYS

Type guard

TRANSCRIPT_KEYS = {"path", "sha256", "bytes", "source"}

def is_transcript_metadata(value: object) -> TypeGuard[dict]:
    return isinstance(value, dict) and set(value) == TRANSCRIPT_KEYS

Prevention

When it happens

Trigger: A results.jsonl transcript_artifacts row carries an extra field, omits one of the four, or uses a renamed key (e.g. 'size' instead of 'bytes'); a hand-edited or third-party runner wrote the row.

Common situations: Runner version skew after a schema change; manual edits to results.jsonl; a forked runner that adds metadata.

Related errors


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