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
- Check and fix permissions: ls -l FILE and chmod u+r FILE (or chown it back to your user)
- 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
- 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
- Gate sources with os.access(path, os.R_OK) before the run
- Run strix as the user who owns the injected files
- Copy privileged files to a user-readable temp location first
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
- '{source}' is not an existing file
- '{spec}' must land inside the workspace: use a relative dest
- '{spec}' has an empty destination path
- '{spec}' has an invalid destination path: {candidate}
- '{spec}' has a control character in its destination path
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/937e3d6b564667df.
Report an issue: GitHub.