{"record":{"id":"9002b01396ef5754","repo":"abhigyanpatwari/GitNexus","slug":"transcript-artifact-changed-while-opening-path","errorCode":null,"errorMessage":"transcript artifact changed while opening: {path}","messagePattern":"transcript artifact changed while opening: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/evolve.py","lineNumber":404,"sourceCode":"    relative, expected_digest, expected_size = _transcript_artifact_metadata(metadata)\n\n    path = _results_artifact_path(root, relative, transcript=True)\n    try:\n        before = path.lstat()\n    except OSError as exc:\n        raise SandboxError(f\"transcript artifact is unavailable: {path}: {exc}\") from exc\n    if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):\n        raise SandboxError(f\"transcript artifact must be a regular non-symlink file: {path}\")\n    if stat.S_IMODE(before.st_mode) & 0o077:\n        raise SandboxError(f\"transcript artifact must be owner-only: {path}\")\n    if before.st_size != expected_size:\n        raise SandboxError(f\"transcript artifact size does not match its results row: {path}\")\n\n    descriptor = os.open(path, os.O_RDONLY | getattr(os, \"O_NOFOLLOW\", 0))\n    try:\n        opened = os.fstat(descriptor)\n        if not stat.S_ISREG(opened.st_mode) or opened.st_dev != before.st_dev or opened.st_ino != before.st_ino:\n            raise SandboxError(f\"transcript artifact changed while opening: {path}\")\n        digest = hashlib.sha256()\n        content = bytearray()\n        while chunk := os.read(descriptor, 64 * 1024):\n            digest.update(chunk)\n            content.extend(chunk)\n            if len(content) > MAX_EVIDENCE_FILE_BYTES:\n                del content[: len(content) - MAX_EVIDENCE_FILE_BYTES]\n        after = os.fstat(descriptor)\n        if (opened.st_size, opened.st_mtime_ns) != (after.st_size, after.st_mtime_ns):\n            raise SandboxError(f\"transcript artifact changed while reading: {path}\")\n    finally:\n        os.close(descriptor)\n    if digest.hexdigest() != expected_digest:\n        raise SandboxError(f\"transcript artifact digest does not match its results row: {path}\")\n    return bytes(content).decode(errors=\"replace\")\n\n\ndef proposer_evidence_entries(","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/evolve.py#L386-L422","documentation":"Raised by `_bound_transcript_artifact` during the open-fstat recheck: after `os.open(... O_NOFOLLOW)`, the descriptor's fstat must still be a regular file on the same device/inode captured by the earlier lstat. A mismatch means the file was swapped between lstat and open (TOCTOU).","triggerScenarios":"Between the initial `path.lstat()` and the subsequent `os.open` + `os.fstat`, the path was replaced (different dev/ino) or changed type. This is a race/tamper signal, not a normal operational condition.","commonSituations":"Another process rewriting the transcript file concurrently with the proposer run, or an adversarial artifact that hot-swaps the path. Extremely rare in normal single-user use.","solutions":["Ensure nothing else writes to the results dir while evolve is reading it (stop concurrent benchmark/restore jobs).","Re-stage the results dir into a location no other process touches, then retry.","If reproducible, audit for a process that is rewriting transcript files and treat as an integrity incident."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from workflow_bench.proposer_sandbox import SandboxError\ntry:\n    proposer_evidence_entries(results_dir=rd, evidence=ev, learnings=lr, gate_summary=gs)\nexcept SandboxError as exc:\n    if 'changed while opening' in str(exc):\n        # TOCTOU: another process touched the results dir mid-read\n        raise RuntimeError('results dir is being modified concurrently; isolate it') from exc\n    raise","preventionTips":["Run evolve against an idle, private copy of the results dir.","Never point two tools at the same results dir simultaneously."],"tags":["python","workflow-bench","sandbox","toctou","race","security"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}