abhigyanpatwari/GitNexus · error · ValueError
phase did not create or change its required artifact: {relat
Error message
phase did not create or change its required artifact: {relative} What it means
Raised by enforce_phase_workspace (runner_artifacts.py:207) when the allowed artifact's state in the 'after' snapshot is identical to its state in the 'before' snapshot. The phase contract says a planning/work phase must create or modify its one declared artifact; an unchanged artifact means the phase produced no evidence and the result is unverifiable.
Source
Thrown at eval/workflow_bench/runner_artifacts.py:207
worktree: Path,
before: dict[str, str],
*,
allowed_artifact: Path,
) -> None:
"""Require a phase to change only its one explicit workspace artifact."""
root = worktree.expanduser().absolute()
artifact = allowed_artifact.expanduser().absolute()
try:
relative = PurePosixPath(artifact.relative_to(root).as_posix())
except ValueError as exc:
raise ValueError(f"phase artifact escapes the workspace: {allowed_artifact}") from exc
after = workspace_snapshot(root)
changed = {path for path in before.keys() | after.keys() if before.get(path) != after.get(path)}
artifact_key = relative.as_posix()
artifact_state = after.get(artifact_key)
if before.get(artifact_key) == artifact_state:
raise ValueError(f"phase did not create or change its required artifact: {relative}")
if artifact_state is None or not artifact_state.startswith("f:"):
raise ValueError(f"phase artifact must be a regular non-symlink file: {relative}")
try:
metadata = artifact.lstat()
descriptor = os.open(artifact, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0))
except OSError as exc:
raise ValueError(f"phase artifact must be a readable regular non-symlink file: {relative}") from exc
try:
opened = os.fstat(descriptor)
if (
stat.S_ISLNK(metadata.st_mode)
or not stat.S_ISREG(metadata.st_mode)
or not stat.S_ISREG(opened.st_mode)
or metadata.st_dev != opened.st_dev
or metadata.st_ino != opened.st_ino
):
raise ValueError(f"phase artifact must be a regular non-symlink file: {relative}")View on GitHub (pinned to d540b00184)
Solutions
- Check the run transcript to see what path the model actually wrote to; align allowed_artifact with that path or fix the prompt.
- Confirm the artifact_key (relative posix path) matches what the model writes — mismatches in casing or trailing slashes cause this.
- If the model genuinely produced nothing, treat it as a failed run (record resolved=False) rather than retry with the same prompt.
Example fix
# before: artifact path does not match what the model writes enforce_phase_workspace(wt, before, allowed_artifact=wt/'docs/plans/plan-v1.md') # model writes docs/plans/plan-v2.md # after enforce_phase_workspace(wt, before, allowed_artifact=wt/'docs/plans/plan-v2.md')
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
import os
artifact = Path(allowed_artifact).expanduser().absolute()
assert artifact.exists(), f"artifact not created: {artifact}"
assert artifact.is_file() and not artifact.is_symlink(), (
f"artifact is not a regular file: {artifact}")
# The phase must have changed it relative to `before` — caller checks the
# snapshot entry, but a quick existence/type check catches the common case. Prevention
- Align the allowed_artifact path with what the model prompt instructs it to write.
- Inspect the run transcript when this fires to find the path the model actually used.
- Do not retry blindly — a phase that produced nothing is a failed run.
When it happens
Trigger: before.get(artifact_key) == artifact_state after the phase ran. The model did not write to the declared artifact path, wrote to a different path, or wrote then reverted it; the artifact path was wrong (typo / wrong directory).
Common situations: The planning prompt told the model to write docs/plans/foo.md but it wrote docs/plans/bar.md; the work phase's artifact is mis-specified relative to what the model actually edits; the model failed silently and produced nothing; the model edited the file but then ran git checkout to revert.
Related errors
- phase artifact must be a regular non-symlink file: {relative
- phase artifact must be a readable regular non-symlink file:
- {label} changed while being read: {path}
- evidence source must be a regular non-symlink file: {path}
- results directory is unavailable: {root}: {exc}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/b893d40a14a59334.
Report an issue: GitHub.