{"record":{"id":"10ed4c48b71b6e51","repo":"affaan-m/ECC","slug":"output-bundle-is-missing","errorCode":null,"errorMessage":"output bundle is missing","messagePattern":"output bundle is missing","errorType":"validation","errorClass":"ContractError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/contract.py","lineNumber":99,"sourceCode":"            if not chunk:\n                break\n            digest.update(chunk)\n    finally:\n        os.close(descriptor)\n    return digest.hexdigest()\n\n\ndef _semantic_signature(spec: dict[str, Any]) -> str:\n    signature = spec.get(\"signature\", {})\n    return json.dumps(signature, sort_keys=True, separators=(\",\", \":\"))\n\n\ndef _validate_output_tree(root: Path) -> None:\n    \"\"\"Reject symlinks and special files before parsing bundle content.\"\"\"\n    try:\n        metadata = root.lstat()\n    except FileNotFoundError:\n        raise ContractError(\"output bundle is missing\") from None\n    if stat.S_ISLNK(metadata.st_mode):\n        raise ContractError(\"output bundle root must not be a symlink\")\n    if not stat.S_ISDIR(metadata.st_mode):\n        raise ContractError(\"output bundle root must be a directory\")\n    pending = [root]\n    while pending:\n        directory = pending.pop()\n        with os.scandir(directory) as entries:\n            for entry in entries:\n                if entry.is_symlink():\n                    raise ContractError(f\"output bundle contains a symlink: {entry.path}\")\n                if entry.is_dir(follow_symlinks=False):\n                    pending.append(Path(entry.path))\n                elif not entry.is_file(follow_symlinks=False):\n                    raise ContractError(f\"output bundle contains a special file: {entry.path}\")\n\n\ndef validate_genre_specs(specs: list[dict[str, Any]]) -> None:","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/contract.py#L81-L117","documentation":"_validate_output_tree checks the output bundle root exists via lstat before parsing content. If the root path does not exist at all, FileNotFoundError is caught and re-raised as this ContractError. It exists so bundle validation fails with a clear, library-specific message instead of a raw filesystem traceback.","triggerScenarios":"Calling validate_bundle with a root path that was never created — e.g. the generation step failed or was skipped, or the path string has a typo.","commonSituations":"Deleting the output directory before validation in CI, running validation from a different working directory than the one used to generate the bundle, typos in CLI/config paths, or a failed generation run silently producing nothing.","solutions":["Verify the path exists: ls <bundle_root>; fix typos or run from the correct directory","Run the generation step first so the output bundle is actually produced","Check whether an earlier pipeline stage deleted/cleaned the output dir before validation","Make the bundle path configurable/absolute in CI to avoid relative-path mismatches"],"exampleFix":"# before\nvalidate_bundle(Path('dist/bundle'))  # never generated\n# after\nfrom pathlib import Path\nbundle = Path('dist/bundle')\nif not bundle.exists():\n    raise SystemExit(f'bundle not generated: run generate first ({bundle})')\nvalidate_bundle(bundle)","handlingStrategy":"validation","validationCode":"from pathlib import Path\nbundle = Path(bundle_arg)\nif not bundle.exists():\n    raise SystemExit(f'output bundle missing: {bundle}')","typeGuard":null,"tryCatchPattern":"try:\n    validate_bundle(root)\nexcept ContractError as e:\n    if 'output bundle is missing' in str(e):\n        print(f'Bundle not found at {root}; run the generation step first')\n    else:\n        raise","preventionTips":["Always run generation before validation in pipelines","Use absolute paths for bundle roots in CI","Check the generation step's exit status before validating"],"tags":["filesystem","path","missing"],"backgroundTag":"file-not-found","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"}