666ghj/MiroFish · error · StarHistoryError

workspace does not exist

Error message

workspace does not exist

What it means

Raised by _safe_workspace() (used by _safe_target) when Path.resolve(strict=True) raises OSError for the workspace path — the workspace directory cannot be resolved because it (or a component of it) does not exist or is inaccessible. This is an environment/configuration guard that runs before any output file is written.

Source

Thrown at scripts/star_history.py:458

    if first_snapshot is not None:
        if first_snapshot < generated_at:
            raise StarHistoryError("first snapshot cannot predate reconstruction")
        if previous_day is not None and previous_day >= first_snapshot.date():
            raise StarHistoryError("reconstruction dates must predate snapshots")


def canonical_state_bytes(state: Mapping[str, Any]) -> bytes:
    validate_state(state)
    return (
        json.dumps(state, ensure_ascii=False, indent=2, sort_keys=True) + "\n"
    ).encode("utf-8")


def _safe_workspace(workspace: Path) -> Path:
    try:
        root = workspace.resolve(strict=True)
    except OSError as exc:
        raise StarHistoryError("workspace does not exist") from exc
    if not root.is_dir():
        raise StarHistoryError("workspace is not a directory")
    return root


def _safe_target(workspace: Path, relative: Path, create_parent: bool) -> Path:
    root = _safe_workspace(workspace)
    if relative.is_absolute() or ".." in relative.parts:
        raise StarHistoryError("output path escaped the workspace")

    current = root
    for part in relative.parts[:-1]:
        current = current / part
        if current.is_symlink():
            raise StarHistoryError("output directory cannot be a symbolic link")
    target = root / relative
    if target.is_symlink():
        raise StarHistoryError("output file cannot be a symbolic link")

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Verify the workspace path exists and is spelled correctly
  2. Create the workspace directory (mkdir -p) before running the script
  3. Check the script's workspace/output configuration option for the correct value
  4. If permissions are the issue, fix ownership/ACLs on the path components

Example fix

# before
workspace = Path("/srv/star-history-out")  # does not exist
# after
workspace = Path("/srv/star-history-out")
workspace.mkdir(parents=True, exist_ok=True)
Defensive patterns

Strategy: validation

Validate before calling

workspace = Path(config["workspace"])
if not workspace.exists():
    raise FileNotFoundError(f"workspace missing: {workspace}")

Type guard

from pathlib import Path

def workspace_exists(workspace: Path) -> bool:
    return workspace.exists()

Try / catch

try:
    write_output(workspace, relative, data)
except StarHistoryError as exc:
    if "workspace does not exist" in str(exc):
        workspace.mkdir(parents=True, exist_ok=True)
        write_output(workspace, relative, data)

Prevention

When it happens

Trigger: Calling any code path that reaches _safe_target (e.g. writing state/output files) with a workspace Path pointing to a missing directory, a path with a nonexistent parent component, or one with permission-denied components.

Common situations: Configuring an output workspace that was never created; a CI job where the workspace dir is created in a later step; typos in the configured workspace path; the directory being cleaned up between runs.

Related errors


AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14). Data as JSON: /api/errors/1318ad33a5e3cb4e. Report an issue: GitHub.