usestrix/strix · error · SpecParseError

Cannot read spec {p}: {exc}

Error message

Cannot read spec {p}: {exc}

What it means

SpecParseError raised by strix.utils.api_spec.load_spec when the API spec file cannot be read — missing path, no permission, or any other OS-level I/O failure. The original OSError is chained as __cause__ so the underlying reason (ENOENT, EACCES, IsADirectoryError) is visible.

Source

Thrown at strix/utils/api_spec.py:50

#: Guard against pathological Postman folder nesting.
_MAX_POSTMAN_DEPTH = 25


class SpecParseError(ValueError):
    """Raised when a spec cannot be read, recognized, or fetched."""


def load_spec(path: str | Path) -> dict[str, Any]:
    """Load an API spec file as a mapping.

    Raises :class:`SpecParseError` if the file cannot be read or is not a
    JSON/YAML mapping.
    """
    p = Path(path)
    try:
        text = p.read_text(encoding="utf-8")
    except OSError as exc:
        raise SpecParseError(f"Cannot read spec {p}: {exc}") from exc
    # JSON is a subset of YAML, so safe_load parses both; try JSON first for a
    # clearer error and to keep the fast path fast.
    try:
        data: Any = json.loads(text)
    except json.JSONDecodeError:
        try:
            data = yaml.safe_load(text)
        except yaml.YAMLError as exc:
            raise SpecParseError(f"{p} is not valid JSON or YAML: {exc}") from exc
    if not isinstance(data, dict):
        raise SpecParseError(f"{p} does not contain a mapping at the top level")
    return data


def classify_spec(raw: dict[str, Any]) -> str | None:
    """Return ``openapi`` / ``swagger`` / ``postman``, or ``None`` if unrecognized."""
    if isinstance(raw.get("openapi"), str):
        return "openapi"

View on GitHub (pinned to 8551339130)

Solutions

  1. Check the path exists and is a file before invoking the scan
  2. Use an absolute path, or verify the file is mounted into the sandbox when running via Docker
  3. Inspect err.__cause__ for the exact OSError reason

Example fix

# before
strix -t https://api.example.com --api-spec specs/openapi.yaml  # wrong cwd

# after
strix -t https://api.example.com --api-spec "$(pwd)/specs/openapi.yaml"
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

p = Path(spec_path)
if not p.is_file():
    raise FileNotFoundError(f"spec not found: {p.resolve()}")

Try / catch

from strix.utils.api_spec import SpecParseError

try:
    spec = load_spec(path)
except SpecParseError as e:
    if str(e).startswith("Cannot read spec"):
        resolve the absolute path / mount the file, then retry once

Prevention

When it happens

Trigger: Passing a spec path that does not exist (strix --api-spec ./openapi.yml typo), a path inside the Docker sandbox that was not mounted, a directory instead of a file, or an unreadable file (mode 000).

Common situations: Relative paths resolved against a different working directory inside the container; file present locally but outside the mounted volume; CI checkout missing the spec file.

Related errors


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