{"record":{"id":"0460759e9e177380","repo":"affaan-m/ECC","slug":"only-local-filesystem-paths-are-supported","errorCode":null,"errorMessage":"Only local filesystem paths are supported","messagePattern":"Only local filesystem paths are supported","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/assets.py","lineNumber":32,"sourceCode":"import struct\nfrom pathlib import Path\nfrom typing import Any\n\nSCHEMA = 'tasteforge.assets.v1'\nMODALITIES = {'image', 'video', '3d_asset'}\nORIGINS = {'local_passthrough', 'external_result', 'recovered_unverified'}\n\n\ndef _text(value: Any, name: str) -> str:\n    if not isinstance(value, str) or not value.strip():\n        raise ValueError(f'{name} must be a nonempty string')\n    return value\n\n\ndef _path(value: Any, base: Path) -> Path:\n    raw = _text(str(value) if isinstance(value, Path) else value, 'path')\n    if '://' in raw or raw.startswith(('file:', 'http:', 'https:')):\n        raise ValueError('Only local filesystem paths are supported')\n    path = Path(raw).expanduser()\n    if not path.is_absolute():\n        path = base / path\n    # Check before resolving '..' to avoid hiding a symlink in the path.\n    for part in (path, *path.parents):\n        if part.is_symlink():\n            raise ValueError(f'Symlinks are not accepted: {part}')\n    return path.resolve()\n\n\ndef _fingerprint(path: Path, modality: str | None = None) -> dict[str, Any]:\n    _path(path, Path.cwd())\n    try:\n        before = path.stat()\n        if not stat.S_ISREG(before.st_mode):\n            raise ValueError(f'Not a regular file: {path}')\n        flags = os.O_RDONLY | getattr(os, 'O_NOFOLLOW', 0) | os.O_NONBLOCK\n        fd = os.open(path, flags)","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/assets.py#L14-L50","documentation":"_path rejects any path containing a URL scheme (\"://\") or starting with file:, http:, or https:. The tasteforge asset pipeline only accepts local filesystem paths so it can hash, fingerprint, and verify files on disk. Remote or URI-style references are refused with this ValueError.","triggerScenarios":"Passing 'https://cdn.example.com/clip.mp4', 'file:///data/clip.mp4', or any URI-scheme path to _fingerprint/_provenance/ingest_assets/validate_assets/_bundle.","commonSituations":"Reusing asset URLs from a web app config; storing references as file:// URIs in a manifest; copying path values from a browser or cloud storage console.","solutions":["Download/copy the asset to the local filesystem and pass its local path.","Strip the file:// scheme and pass the plain absolute path.","If inputs come from URLs, add a fetch step that materializes files locally first.","Sanitize manifests to contain only local paths before ingestion."],"exampleFix":"// before\ningest_assets(sp, paths=[\"https://cdn.example.com/clip.mp4\"])\n\n// after\nlocal = download_to_tmp(\"https://cdn.example.com/clip.mp4\")  # e.g. /tmp/clip.mp4\ningest_assets(sp, paths=[local])","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\ndef is_local_path(p: str) -> bool:\n    return not (\"://\" in p or p.startswith((\"file:\", \"http:\", \"https:\")))","typeGuard":"def is_filesystem_path(v) -> bool:\n    return isinstance(v, (str, Path)) and \"://\" not in str(v) and not str(v).startswith((\"file:\", \"http:\", \"https:\"))","tryCatchPattern":"try:\n    assets = ingest_assets(sp, paths=paths)\nexcept ValueError as e:\n    if \"Only local filesystem paths\" in str(e):\n        paths = [materialize(p) for p in paths]  # download URLs to disk\n        assets = ingest_assets(sp, paths=paths)\n    else:\n        raise","preventionTips":["Keep a download/materialization step between URL sources and asset ingestion.","Store plain absolute paths, not file:// URIs, in manifests.","Lint configs for http(s):// in path fields."],"tags":["url","local-files-only","input-validation"],"backgroundTag":"unsupported-source-type","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}