calesthio/OpenMontage · critical · KlingAPIError
KLING_API_KEY is not set. Configure KLING_API_KEY for offici
Error message
KLING_API_KEY is not set. Configure KLING_API_KEY for official Kling API access.
What it means
KlingAPIError (with http_status=401) raised lazily by the client's headers property whenever an authenticated request is attempted and self.api_key is falsy. The key is read once at construction from the KLING_API_KEY environment variable; if it wasn't set and no explicit api_key was passed, every request fails here with an actionable message naming the exact env var.
Source
Thrown at tools/_kling/client.py:43
class KlingClient:
"""Small synchronous client for the official Kling API."""
def __init__(
self,
api_key: str | None = None,
base_url: str | None = None,
session: Any | None = None,
max_retries: int = 2,
) -> None:
self.api_key = api_key if api_key is not None else os.environ.get("KLING_API_KEY")
self.base_url = (base_url or os.environ.get("KLING_API_BASE_URL") or DEFAULT_API_BASE_URL).rstrip("/")
self.session = session or requests.Session()
self.max_retries = max_retries
@property
def headers(self) -> dict[str, str]:
if not self.api_key:
raise KlingAPIError(
"KLING_API_KEY is not set. Configure KLING_API_KEY for official Kling API access.",
http_status=401,
)
return {
"Authorization": f"Bearer {self.api_key}",
"Accept": "application/json",
"Content-Type": "application/json",
}
def post(self, path: str, payload: dict[str, Any]) -> dict[str, Any]:
return self._request("post", path, json=payload)
def get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
return self._request("get", path, params=params)
def download(self, url: str, output_path: Path, timeout: int = 180) -> Path:
output_path.parent.mkdir(parents=True, exist_ok=True)
response = self.session.get(url, timeout=timeout)View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Export KLING_API_KEY in the environment where the process runs: export KLING_API_KEY=... (or add to .env + load it)
- Pass api_key explicitly to the KlingClient constructor when managing secrets programmatically (e.g. from a secrets manager)
- Verify with: python -c "import os; print(bool(os.environ.get('KLING_API_KEY')))"
- In CI, add KLING_API_KEY to the runner's secret store / masked variables
Example fix
# before client = KlingClient() # env var not set -> 401 KlingAPIError on first request # after client = KlingClient(api_key=os.environ["KLING_API_KEY"]) # fail fast at construction
Defensive patterns
Strategy: validation
Validate before calling
import os
if not os.environ.get("KLING_API_KEY"):
raise SystemExit("KLING_API_KEY not set — export it before running Kling tools")
client = KlingClient() Type guard
def kling_credentials_present() -> bool:
return bool(os.environ.get("KLING_API_KEY")) Try / catch
try:
client.get("/v1/models/test") # any cheap authenticated call
except KlingAPIError as e:
if getattr(e, "http_status", None) == 401 and "KLING_API_KEY" in str(e):
raise SystemExit("configure KLING_API_KEY (env var or KlingClient(api_key=...))")
raise Prevention
- Fail fast at process start, not on first request: assert the env var before constructing the client
- Load .env explicitly (python-dotenv) rather than assuming auto-load
- Add the secret to CI masked variables; pass api_key from a secrets manager in production
When it happens
Trigger: Constructing KlingClient in a shell/process where KLING_API_KEY was never exported; CI runners or agent sessions missing the secret; .env file present but not loaded; key passed as empty string (also falsy); subprocess spawning the client without inheriting the environment.
Common situations: New machine/container without the env var; direnv/pyenv activation missed; secret stored in .env but the process doesn't auto-load it; the key name typo'd (KLING_APIKEY / KLING_KEY).
Related errors
- {name} failed: {result.error}
- Kling result did not include a remote video URL for lip-sync
- Avatar smoke requires an existing narration file: {narration
- callback_url must be an absolute http(s) URL
- Kling Classic create response missing data.task_id: {data}
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/98f6c8d8329217ee.
Report an issue: GitHub.