{"record":{"id":"6e3b129566de3fd8","repo":"abhigyanpatwari/GitNexus","slug":"transcript-artifact-byte-count-must-be-an-integer","errorCode":null,"errorMessage":"transcript artifact byte count must be an integer","messagePattern":"transcript artifact byte count must be an integer","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/evolve.py","lineNumber":338,"sourceCode":"        if transcript and stat.S_IMODE(metadata.st_mode) & 0o077:\n            raise SandboxError(f\"transcript artifact parent must be owner-only: {current}\")\n    return root / Path(*relative.parts)\n\n\ndef _transcript_artifact_metadata(metadata: Any) -> tuple[str, str, int]:\n    \"\"\"Validate transcript metadata without touching any host path.\"\"\"\n\n    if not isinstance(metadata, dict) or set(metadata) != {\"path\", \"sha256\", \"bytes\", \"source\"}:\n        raise SandboxError(\"transcript artifact metadata must contain only path, sha256, bytes, and source\")\n    relative = metadata[\"path\"]\n    expected_digest = metadata[\"sha256\"]\n    expected_size = metadata[\"bytes\"]\n    if metadata[\"source\"] != runner_sessions.PARENT_EVENT_STREAM_SOURCE:\n        raise SandboxError(\"transcript artifact source is not the parent event stream\")\n    if not isinstance(relative, str) or not re.fullmatch(r\"[0-9a-f]{64}\", str(expected_digest)):\n        raise SandboxError(\"transcript artifact metadata is malformed\")\n    if not isinstance(expected_size, int) or isinstance(expected_size, bool):\n        raise SandboxError(\"transcript artifact byte count must be an integer\")\n    if expected_size < 0 or expected_size > runner.MAX_TRANSCRIPT_BYTES:\n        raise SandboxError(\"transcript artifact exceeds the bounded run-output limit\")\n    return relative, expected_digest, expected_size\n\n\ndef _normalized_transcript_artifact_path(relative_value: str) -> str:\n    \"\"\"Apply the transcript path contract without touching the filesystem.\"\"\"\n\n    relative = PurePosixPath(relative_value)\n    if (\n        relative.is_absolute()\n        or len(relative.parts) != 2\n        or relative.parts[0] != \"transcripts\"\n        or any(part in {\"\", \".\", \"..\"} for part in relative.parts)\n    ):\n        raise SandboxError(f\"unsafe results artifact path: {relative_value!r}\")\n    return relative.as_posix()\n","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/evolve.py#L320-L356","documentation":"The 'bytes' field must be a real integer. bool is explicitly rejected (`isinstance(expected_size, bool)`) even though bool subclasses int in Python, because True/False would silently coerce to 1/0 and bypass the size bound. float, str, and None are rejected for the same reason: the size bound must be exact.","triggerScenarios":"bytes = true/false (e.g. a flag mis-serialized into the field); bytes = 12.0 (float); bytes = '12' (JSON string); bytes = None; a NumPy int that is not a Python int.","commonSituations":"Schema drift where a boolean flag overwrote the size; JSON decoded with non-strict numerics; a third-party writer that stringified numbers.","solutions":["Write bytes as a Python int: `len(content)` or `path.stat().st_size`.","Validate before serializing: `assert isinstance(n, int) and not isinstance(n, bool)`.","Re-encode the row with json.dumps after coercing `int(size)`."],"exampleFix":"# before\n{\"path\": \"transcripts/r.json\", \"sha256\": \"<64hex>\", \"bytes\": True, \"source\": \"parent-captured-stream-json\"}\n\n# after\nsize = path.stat().st_size\nassert isinstance(size, int) and not isinstance(size, bool)\nrow = {\"path\": \"transcripts/r.json\", \"sha256\": digest, \"bytes\": size, \"source\": PARENT_EVENT_STREAM_SOURCE}","handlingStrategy":"type-guard","validationCode":"def is_real_int_bytes(value: object) -> bool:\n    return isinstance(value, int) and not isinstance(value, bool) and value >= 0","typeGuard":"def is_nonneg_python_int(value: object) -> TypeGuard[int]:\n    # bool is a subclass of int; exclude it explicitly.\n    return isinstance(value, int) and not isinstance(value, bool)","tryCatchPattern":null,"preventionTips":["Always set bytes to path.stat().st_size (a real int).","Assert `isinstance(n, int) and not isinstance(n, bool)` before serializing.","Reject JSON where numbers were stringified; re-encode with json.dumps after int coercion."],"tags":["workflow-bench","sandbox","schema","type-safety","transcript","validation"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}