usestrix/strix · error · ValueError

Cannot read '{source}': {error}

Error message

Cannot read '{source}': {error}

What it means

Raised by resolve_workspace_files() when the source file exists but cannot be opened for reading (an OSError from source.open('rb')). This catches permission problems and races (file deleted or locked between the is_file() check and the open), converting the OSError into a user-facing ValueError.

Source

Thrown at strix/interface/utils.py:1734

    """Validate ``PATH[:DEST]`` specs into source/destination pairs.

    Each spec names a readable host file. ``DEST`` is the path inside
    ``/workspace``; it defaults to the file name. Raises ``ValueError`` with a
    user-facing message when a spec is unusable.
    """
    resolved: list[dict[str, str]] = []
    seen: dict[str, str] = {}
    for spec in specs or []:
        raw, sep, dest = spec.rpartition(":")
        source_text = raw if sep and dest.strip() else spec
        source = Path(source_text.strip()).expanduser()
        if not source.is_file():
            raise ValueError(f"'{source}' is not an existing file")
        try:
            with source.open("rb"):
                pass
        except OSError as error:
            raise ValueError(f"Cannot read '{source}': {error}") from error
        workspace_rel = _workspace_file_dest(spec, source)
        if workspace_rel in seen:
            raise ValueError(
                f"Two workspace files target /workspace/{workspace_rel}: "
                f"'{seen[workspace_rel]}' and '{source}'"
            )
        seen[workspace_rel] = str(source)
        resolved.append(
            {
                "source_path": str(source.resolve()),
                "workspace_path": f"/workspace/{workspace_rel}",
            }
        )
    return resolved


def read_workspace_files(workspace_files: list[dict[str, str]] | None) -> list[dict[str, Any]]:
    """Read resolved workspace files into engine ``extra_files`` entries."""

View on GitHub (pinned to 8551339130)

Solutions

  1. Check and fix permissions: ls -l FILE and chmod u+r FILE (or chown it back to your user)
  2. Copy the file to a readable location first: sudo cp /root/secret.key /tmp/secret.key && sudo chown $(id -un) /tmp/secret.key, then pass the copy
  3. Verify readability before the run: test -r FILE && strix --workspace-file FILE:secret.key ... || echo 'unreadable'

Example fix

# before
strix --workspace-file /root/secret.key:secret.key -t ./   # permission denied
# after
sudo cp /root/secret.key /tmp/secret.key && sudo chown "$(id -un):" /tmp/secret.key
strix --workspace-file /tmp/secret.key:secret.key -t ./
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

def readable(p: str) -> bool:
    path = Path(p).expanduser()
    return path.is_file() and os.access(path, os.R_OK)

Try / catch

try:
    resolve_workspace_files(specs)
except ValueError as e:
    if 'Cannot read' in str(e):
        fix_permissions_or_copy_file()
    else:
        raise

Prevention

When it happens

Trigger: The source exists but the current user lacks read permission (chmod 000, root-owned file, other user's home), the file sits on an unreadable mount, or it disappears between the is_file() check and the open (TOCTOU race in concurrent scripts).

Common situations: Running strix as a different user/sudo context than the file owner; files under /root or another account's home; SELinux/AppArmor denying read; files on an NFS/FUSE mount with restrictive perms; macOS sandboxed terminal denied file access.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/937e3d6b564667df. Report an issue: GitHub.