affaan-m/ECC · error · ContractError

receipt source is not a regular file

Error message

receipt source is not a regular file: {path}

What it means

_sha256 opened the receipt path with O_NOFOLLOW successfully, but fstat shows the opened file is not a regular file (e.g. a FIFO, device node, or directory-like special file). The library only accepts regular files as receipt sources so the digest corresponds to stable on-disk bytes.

Solutions

  1. Point the receipt argument at an actual regular file on disk
  2. Check what the path is: ls -la <path> or stat <path> and fix the config/variable
  3. If reading from a pipe/stdin, first write the content to a temp regular file and validate that
  4. Regenerate the receipt file if the artifact pipeline left it as a special file

Example fix

# before
receipt_path = '/dev/stdin'
# after
import tempfile, shutil, sys
with tempfile.NamedTemporaryFile(delete=False) as tmp:
    shutil.copyfileobj(sys.stdin, tmp)
    receipt_path = tmp.name
Defensive patterns

Strategy: validation

Validate before calling

import stat, os
md = os.lstat(path)
assert stat.S_ISREG(md.st_mode), f'{path} is not a regular file'

Type guard

def is_regular_file(path) -> bool:
    import stat, os
    try:
        return stat.S_ISREG(os.lstat(path).st_mode)
    except OSError:
        return False

Try / catch

try:
    validate_artifact_receipt(root)
except ContractError as e:
    if 'not a regular file' in str(e):
        print(f'Receipt must be a regular file: {e}')
    else:
        raise

Prevention

When it happens

Trigger: Passing a path that is a character device, FIFO/pipe, socket, or other special file as the receipt path to validate_artifact_receipt. This check runs after open+fstat, so it catches files that are special even if they passed a path lookup.

Common situations: Pointing the receipt argument at /dev/stdin, a named pipe used for streaming, a device file, or a directory by mistake in scripts/CI configs.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/5eacfb8cb75ba36b. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/contract.py:78

            raise ContractError(f"{label} has invalid {field}")
        for value in values:
            _validate_media_time(value, source_duration, label=f"{label} {field}")
    samples = probe.get("style_samples", [])
    if not isinstance(samples, list) or any(not isinstance(sample, dict) for sample in samples):
        raise ContractError(f"{label} has invalid style evidence")
    for sample in samples:
        _validate_media_time(sample.get("time"), source_duration, label=f"{label} style evidence")


def _sha256(path: Path) -> str:
    if not hasattr(os, "O_NOFOLLOW"):
        raise ContractError("secure receipt validation requires O_NOFOLLOW")
    descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
    digest = hashlib.sha256()
    try:
        metadata = os.fstat(descriptor)
        if not stat.S_ISREG(metadata.st_mode):
            raise ContractError(f"receipt source is not a regular file: {path}")
        while True:
            chunk = os.read(descriptor, 1024 * 1024)
            if not chunk:
                break
            digest.update(chunk)
    finally:
        os.close(descriptor)
    return digest.hexdigest()


def _semantic_signature(spec: dict[str, Any]) -> str:
    signature = spec.get("signature", {})
    return json.dumps(signature, sort_keys=True, separators=(",", ":"))


def _validate_output_tree(root: Path) -> None:
    """Reject symlinks and special files before parsing bundle content."""
    try:

View on GitHub (pinned to 8321021c54)