affaan-m/ECC · error · FileNotFoundError
Spec file not found: {path}
Error message
Spec file not found: {path} What it means
Raised by parse_spec() in skill-comply when the supplied YAML compliance-spec path does not resolve to an existing regular file. The guard is path.is_file() at the top of the function, identical in shape to parse_trace's file check.
Source
Thrown at skills/skill-comply/scripts/parser.py:80
try:
events.append(ObservationEvent(
timestamp=raw["timestamp"],
event=raw["event"],
tool=raw["tool"],
session=raw["session"],
input=raw.get("input", ""),
output=raw.get("output", ""),
))
except KeyError as e:
raise ValueError(f"Missing required field {e} at line {i}") from e
return sorted(events, key=lambda e: e.timestamp)
def parse_spec(path: Path) -> ComplianceSpec:
"""Parse a YAML compliance spec file."""
if not path.is_file():
raise FileNotFoundError(f"Spec file not found: {path}")
raw = yaml.safe_load(path.read_text())
steps: list[Step] = []
for s in raw["steps"]:
d = s["detector"]
steps.append(Step(
id=s["id"],
description=s["description"],
required=s["required"],
detector=Detector(
description=d["description"],
after_step=d.get("after_step"),
before_step=d.get("before_step"),
),
))
if "scoring" not in raw:
raise KeyError("Missing 'scoring' section in compliance spec")View on GitHub (pinned to 01e15490f0)
Solutions
- Confirm path.is_file() at the call site and log path.resolve().
- Use the canonical specs/ directory under the skill-comply package, derived from __file__ rather than hardcoded strings.
- Expand user paths with Path.expanduser().
- If the spec was generated, ensure spec_generator.generate_spec completed and its tempfile was not deleted before parse_spec ran.
Example fix
# before
spec = parse_spec(Path('specs/skill.yaml'))
# after
from pathlib import Path
spec_path = (Path(__file__).parent / 'specs' / 'skill.yaml').resolve()
if not spec_path.is_file():
raise SystemExit(f'spec missing: {spec_path}')
spec = parse_spec(spec_path) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def safe_parse_spec(path: Path):
resolved = Path(path).expanduser().resolve()
if not resolved.is_file():
raise SystemExit(f'spec not found: {resolved}')
from scripts.parser import parse_spec
return parse_spec(resolved) Try / catch
from scripts.parser import parse_spec
try:
spec = parse_spec(path)
except FileNotFoundError as e:
raise SystemExit(f'compliance spec missing: {e}') from e Prevention
- Locate specs via package-relative paths: Path(__file__).parent / 'specs' / name.
- If generate_spec is the producer, do not unlink its tempfile until parse_spec has finished.
- Treat an absent spec as a build error, not a runtime error — fail fast in CI.
When it happens
Trigger: Passing a stale spec path; a Path constructed from a config value that points at the wrong directory; an unexpanded '~'; pointing at a directory instead of a .yaml file.
Common situations: generate_spec wrote the spec to a tempfile that was already unlinked; CI checkout missing the specs/ directory; a CLI flag that takes the spec path was left at its default.
Related errors
- Missing 'scoring' section in compliance spec
- Trace file not found: {path}
- Invalid JSON at line {i}: {e}
- Missing required field {e} at line {i}
- Unknown model: {model!r}. Allowed: {ALLOWED_MODELS}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/3c7a561b5eba6b91.
Report an issue: GitHub.