can1357/oh-my-pi · error · RuntimeError

No artifacts directory found: {artifacts_dir}

Error message

No artifacts directory found: {artifacts_dir}

What it means

output() resolves the artifacts directory (from PI_ARTIFACTS_DIR or PI_SESSION_FILE) and requires that the directory already exist on disk; if it doesn't, it emits an error status and raises RuntimeError 'No artifacts directory found: <path>'. The harness is expected to have created the directory when the session started — output() never creates it implicitly.

Source

Thrown at packages/coding-agent/src/eval/py/prelude.py:187

            output('scout_0', query='.files[0]')  # Extract JSON field
            output('scout_0', offset=10, limit=20)  # Lines 10-29
            output('scout_0', 'reviewer_1')  # Read multiple outputs
        """
        # Prefer PI_ARTIFACTS_DIR so subagents resolve through the parent's
        # shared artifacts dir; fall back to deriving from PI_SESSION_FILE
        # for legacy callers / top-level sessions where the two coincide.
        artifacts_dir = os.environ.get("PI_ARTIFACTS_DIR")
        if not artifacts_dir:
            session_file = os.environ.get("PI_SESSION_FILE")
            if not session_file:
                _emit_status("output", error="No session file available")
                raise RuntimeError("No session - output artifacts unavailable")
            artifacts_dir = session_file.rsplit(".", 1)[0]  # Strip .jsonl extension
        if not Path(artifacts_dir).exists():
            _emit_status(
                "output", error="Artifacts directory not found", path=artifacts_dir
            )
            raise RuntimeError(f"No artifacts directory found: {artifacts_dir}")

        if not ids:
            _emit_status("output", error="No IDs provided")
            raise ValueError("At least one output ID is required")

        if query and (offset is not None or limit is not None):
            _emit_status("output", error="query cannot be combined with offset/limit")
            raise ValueError("query cannot be combined with offset/limit")

        results: list[dict] = []
        not_found: list[str] = []

        for output_id in ids:
            output_path = Path(artifacts_dir) / f"{output_id}.md"
            if not output_path.exists():
                not_found.append(output_id)
                continue

View on GitHub (pinned to 9690622007)

Solutions

  1. Create the directory before calling output(): os.makedirs(artifacts_dir, exist_ok=True).
  2. Point PI_ARTIFACTS_DIR at a directory that exists for the current session.
  3. If PI_SESSION_FILE was moved/renamed, ensure the sibling artifacts directory matches its new path.
  4. Re-run through the harness so it recreates the session's artifacts directory.

Example fix

# before
output(ids=["result"])  # artifacts dir cleaned up
# after
import os
artifacts = os.environ["PI_ARTIFACTS_DIR"]
os.makedirs(artifacts, exist_ok=True)
output(ids=["result"])
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path
dir_ = os.environ.get('PI_ARTIFACTS_DIR') or os.environ.get('PI_SESSION_FILE', '').rsplit('.', 1)[0]
if dir_ and not Path(dir_).exists():
    os.makedirs(dir_, exist_ok=True)

Type guard

def artifacts_ready():
    d = os.environ.get('PI_ARTIFACTS_DIR') or os.environ.get('PI_SESSION_FILE', '').rsplit('.', 1)[0]
    return bool(d) and Path(d).is_dir()

Try / catch

try:
    output(ids=['result'])
except RuntimeError as e:
    if str(e).startswith('No artifacts directory found'):
        os.makedirs(e.args[0].rsplit(': ', 1)[-1], exist_ok=True)
        output(ids=['result'])
    else:
        raise

Prevention

When it happens

Trigger: PI_ARTIFACTS_DIR pointing at a deleted/never-created directory, PI_SESSION_FILE set to a path whose sibling artifacts dir (session path minus .jsonl) was cleaned up, a stale env var left over from a previous session, or a typo in the configured path.

Common situations: Re-running a script after tmp cleanup removed the artifacts dir; copying PI_SESSION_FILE/PI_ARTIFACTS_DIR between machines or containers; resuming an old session file whose artifacts directory was garbage-collected.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/24110100e0f9d4e5. Report an issue: GitHub.