affaan-m/ECC · error · MissingKeyError
FAL_KEY is not set. Get a key at…
Error message
FAL_KEY is not set.
Get a key at https://fal.ai/dashboard/keys, then either:
export FAL_KEY='...'
or run the pipeline offline with no key and no spend:
export {DRY_RUN_ENV}=1 (or pass --dry-run) What it means
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.
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.
Example fix
# before python -m taste.pipeline run # MissingKeyError: FAL_KEY is not set. # after export FAL_KEY='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:secret' python -m taste.pipeline run
Defensive patterns
Strategy: try-catch
Validate before calling
import os
if not os.environ.get("FAL_KEY", "").strip():
raise SystemExit("FAL_KEY is not set; export it or use --dry-run") Type guard
def has_fal_key(env: dict[str, str]) -> bool:
return bool(env.get("FAL_KEY", "").strip()) Try / catch
try:
result = generate(...)
except MissingKeyError:
logger.warning("no FAL_KEY; falling back to dry-run mode")
result = generate(dry_run=True) Prevention
- 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
When it happens
Trigger: 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().
Common situations: 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.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- discussion is not an Announcement
- FAL_KEY is not set. Get a key at…
- msg
- Announcements discussion category is required
- application bundle differs from its bound evidence
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/1133fba2d2a290ca.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/taste/falapi.py:199
if os.environ.get("TASTE_FORGE_ALLOW_LIVE") != "1":
raise FalError("live transport requires TASTE_FORGE_ALLOW_LIVE=1")
def safe_url(url: str) -> str:
"""Log only origin: paths, queries and userinfo can carry signed secrets."""
try:
parsed = urllib.parse.urlsplit(url)
return f"{parsed.scheme}://{parsed.hostname or '[invalid-host]'}"
except ValueError:
return "[invalid-url]"
def api_key() -> str:
"""Return ``FAL_KEY`` after live opt-in. Never logs the value."""
require_live()
key = os.environ.get("FAL_KEY", "").strip()
if not key:
raise MissingKeyError(
"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"
f" export {DRY_RUN_ENV}=1 (or pass --dry-run)"
)
return key
def _fal():
"""Import ``fal_client`` lazily so dry runs work even if it is absent."""
try:
import fal_client # noqa: PLC0415 - deliberate lazy import
except ImportError as exc: # pragma: no cover - environment dependent
raise FalError(
"the 'fal_client' package is required for live calls: pip install fal-client"
) from exc
return fal_clientView on GitHub (pinned to 8321021c54)