{"record":{"id":"1133fba2d2a290ca","repo":"affaan-m/ECC","slug":"fal-key-is-not-set-get-a-key-at-https-fal-ai-dashboard-keys-1133fb","errorCode":null,"errorMessage":"FAL_KEY is not set.\n  Get a key at https://fal.ai/dashboard/keys, then either:\n    export FAL_KEY='...'\n  or run the pipeline offline with no key and no spend:\n    export {DRY_RUN_ENV}=1      (or pass --dry-run)","messagePattern":"FAL_KEY is not set\\.\n  Get a key at https://fal\\.ai/dashboard/keys, then either:\n    export FAL_KEY='\\.\\.\\.'\n  or run the pipeline offline with no key and no spend:\n    export (.+?)=1      \\(or pass --dry-run\\)","errorType":"exception","errorClass":"MissingKeyError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/falapi.py","lineNumber":199,"sourceCode":"    if os.environ.get(\"TASTE_FORGE_ALLOW_LIVE\") != \"1\":\n        raise FalError(\"live transport requires TASTE_FORGE_ALLOW_LIVE=1\")\n\n\ndef safe_url(url: str) -> str:\n    \"\"\"Log only origin: paths, queries and userinfo can carry signed secrets.\"\"\"\n    try:\n        parsed = urllib.parse.urlsplit(url)\n        return f\"{parsed.scheme}://{parsed.hostname or '[invalid-host]'}\"\n    except ValueError:\n        return \"[invalid-url]\"\n\n\ndef api_key() -> str:\n    \"\"\"Return ``FAL_KEY`` after live opt-in. Never logs the value.\"\"\"\n    require_live()\n    key = os.environ.get(\"FAL_KEY\", \"\").strip()\n    if not key:\n        raise MissingKeyError(\n            \"FAL_KEY is not set.\\n\"\n            \"  Get a key at https://fal.ai/dashboard/keys, then either:\\n\"\n            \"    export FAL_KEY='...'\\n\"\n            \"  or run the pipeline offline with no key and no spend:\\n\"\n            f\"    export {DRY_RUN_ENV}=1      (or pass --dry-run)\"\n        )\n    return key\n\n\ndef _fal():\n    \"\"\"Import ``fal_client`` lazily so dry runs work even if it is absent.\"\"\"\n    try:\n        import fal_client  # noqa: PLC0415 - deliberate lazy import\n    except ImportError as exc:  # pragma: no cover - environment dependent\n        raise FalError(\n            \"the 'fal_client' package is required for live calls: pip install fal-client\"\n        ) from exc\n    return fal_client","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/falapi.py#L181-L217","documentation":"falapi.api_key() reads the FAL_KEY environment variable after confirming the caller opted into live mode (require_live()). If the variable is unset or empty/whitespace, it raises MissingKeyError with instructions for obtaining a key at fal.ai/dashboard/keys. This guards against making paid fal.ai calls without credentials and points users at the offline --dry-run mode as a no-cost alternative.","triggerScenarios":"Calling any live API path — api_key() is invoked by submit() and upload() — when os.environ['FAL_KEY'] is missing, empty, or contains only whitespace after strip(), and live mode has already been opted into via require_live().","commonSituations":"Fresh clone without a .env file; CI environment where the secret was never injected; running inside a container/sandbox that does not inherit shell exports; exporting FAL_KEY in one shell but running the script in another; typo like FAL_KEYS or fal_key; using `set FAL_KEY=...` (cmd.exe) syntax in bash or vice versa.","solutions":["Export the key in the current shell: export FAL_KEY='your-key-here' (obtain it at https://fal.ai/dashboard/keys).","Persist the key in your environment (.env file loaded by the pipeline, shell profile, or CI secret store) so it survives new sessions.","If you do not want to spend, run offline instead: export DRY_RUN_ENV=1 or pass --dry-run, which skips live calls entirely.","Check for typos in the variable name and confirm it is exported (not just a local shell variable) and visible in the same environment the script runs in."],"exampleFix":"# before\npython -m taste.pipeline run   # MissingKeyError: FAL_KEY is not set.\n\n# after\nexport FAL_KEY='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:secret'\npython -m taste.pipeline run","handlingStrategy":"try-catch","validationCode":"import os\nif not os.environ.get(\"FAL_KEY\", \"\").strip():\n    raise SystemExit(\"FAL_KEY is not set; export it or use --dry-run\")","typeGuard":"def has_fal_key(env: dict[str, str]) -> bool:\n    return bool(env.get(\"FAL_KEY\", \"\").strip())","tryCatchPattern":"try:\n    result = generate(...)\nexcept MissingKeyError:\n    logger.warning(\"no FAL_KEY; falling back to dry-run mode\")\n    result = generate(dry_run=True)","preventionTips":["Set FAL_KEY in a .env file loaded at startup and validate it in an early sanity check","Keep dry-run mode wired into scripts so missing keys degrade gracefully instead of crashing","Never hardcode the key or echo it into logs; reference only its presence","In CI, inject FAL_KEY via the secret store and assert non-empty before the job runs"],"tags":["python","api-key","environment","configuration"],"backgroundTag":"missing-env-var","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"}