{"record":{"id":"976f4eea63797dea","repo":"affaan-m/ECC","slug":"distill-failed-exc-976f4e","errorCode":null,"errorMessage":"distill failed: {exc}","messagePattern":"distill failed: (.+?)","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/taste-distillation/scripts/distill.py","lineNumber":514,"sourceCode":"                    help=\"stub every network call; no API key needed, no spend\")\n    ap.add_argument(\"--verbose\", \"-v\", action=\"store_true\")\n    a = ap.parse_args()\n\n    logging.basicConfig(\n        level=logging.DEBUG if a.verbose else logging.INFO,\n        format=\"%(levelname)s %(name)s: %(message)s\",\n    )\n    if a.dry_run:\n        falapi.enable_dry_run()\n\n    try:\n        # Check credentials before uploading anything, so a missing key costs\n        # nothing and reports once.\n        if not falapi.is_dry_run():\n            falapi.api_key()\n        distill(a.genre, a.root, a.max_stills, a.props)\n    except (FileNotFoundError, falapi.FalError) as exc:\n        raise SystemExit(f\"distill failed: {exc}\") from exc\n\n\nif __name__ == \"__main__\":\n    main()\n","sourceCodeStart":496,"sourceCodeEnd":519,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-distillation/scripts/distill.py#L496-L519","documentation":"main() wraps the distill run in a try/except for FileNotFoundError and falapi.FalError and re-raises as SystemExit('distill failed: ...'). This is the CLI's top-level error handler: missing pack files or FAL API errors are converted into a single clean fatal message after credentials are checked pre-upload so a missing key costs nothing.","triggerScenarios":"main() -> distill() chain raises falapi.FalError (bad/missing FAL key, tier/endpoint errors, live-transport not authorized) or FileNotFoundError (missing still/reference files) after the credential pre-check passes.","commonSituations":"Running with live mode but an invalid FAL API key; missing uploaded still file deleted between check and upload;FalError from use_tier or require_live propagating out of distill; network/API failure during submission.","solutions":["Read the exception text after 'distill failed:' — it contains the underlying FileNotFoundError or FalError detail; fix that root cause.","Verify FAL_KEY is set and valid, or set the dry-run env var to run without credentials.","If live transport is intended, set TASTE_FORGE_ALLOW_LIVE=1 (see require_live).","Confirm all pack files (stills, props) exist on disk before running the command.","Check FAL API status/quotas if the error indicates request failure."],"exampleFix":"// before\npython distill.py cinematic  # SystemExit: distill failed: FalError(...)\n\n// after\nexport FAL_KEY=...          # or TASTE_FORGE_DRY_RUN=1 for dry run\nexport TASTE_FORGE_ALLOW_LIVE=1\npython distill.py cinematic","handlingStrategy":"try-catch","validationCode":"if not os.environ.get(\"FAL_KEY\") and not falapi.is_dry_run():\n    raise SystemExit(\"FAL_KEY is not set; use dry-run or export FAL_KEY\")","typeGuard":"null","tryCatchPattern":"try:\n    distill(a.genre, a.root, a.max_stills, a.props)\nexcept (FileNotFoundError, falapi.FalError) as exc:\n    log.error(\"distill failed: %s\", exc)\n    raise SystemExit(1) from exc","preventionTips":["Pre-check credentials (as main() already does) before any upload","Set TASTE_FORGE_ALLOW_LIVE=1 deliberately when live mode is intended","Keep pack files intact between pipeline steps","Catch the underlying FalError/FileNotFoundError to surface root causes, not just 'distill failed'","Run a dry run first when testing new genres or configs"],"tags":["cli","error-handling","api","credentials"],"backgroundTag":"api-error-response","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"}