mvanhorn/last30days-skill · critical · RuntimeError
OpenRouter selected but OPENROUTER_API_KEY is not configured
Error message
OpenRouter selected but OPENROUTER_API_KEY is not configured.
What it means
RuntimeError raised in resolve_runtime when provider is 'openrouter' but OPENROUTER_API_KEY is absent from config. Unlike the big-three providers the key is read inline from the config dict at this branch, so it must be present in whatever env/.env layer populates config.
Source
Thrown at skills/last30days/scripts/lib/providers.py:305
openai_token
)
if provider_name == "xai":
if not xai_key:
raise RuntimeError("xAI selected but XAI_API_KEY is not configured.")
runtime = schema.ProviderRuntime(
reasoning_provider="xai",
planner_model=planner_model,
rerank_model=rerank_model,
x_search_backend=_resolve_x_backend(config),
)
return runtime, XAIClient(xai_key)
if provider_name == "openrouter":
openrouter_key = config.get("OPENROUTER_API_KEY")
if not openrouter_key:
raise RuntimeError("OpenRouter selected but OPENROUTER_API_KEY is not configured.")
runtime = schema.ProviderRuntime(
reasoning_provider="openrouter",
planner_model=planner_model,
rerank_model=rerank_model,
x_search_backend=_resolve_x_backend(config),
)
return runtime, OpenRouterClient(openrouter_key)
raise RuntimeError(f"Unsupported reasoning provider: {provider_name}")
def _resolve_x_backend(config: dict[str, Any]) -> str | None:
"""Resolve the X backend for runtime fetch.
Delegates to env.get_x_source which handles:
- Any known pin (X_BACKEND_KNOWN) exclusively: returns pin if available, None otherwise
- Unpinned: walks auto-chain (X_BACKEND_ORDER) only, never auto-selects opt-in backends
"""View on GitHub (pinned to c7460f6114)
Solutions
- Add OPENROUTER_API_KEY to the loaded env layer (.env file or process env)
- Verify the harness/gateway invoking the engine passes the variable through
- Test with a trivial config load before the full run to confirm the key resolves
Example fix
# before LAST30DAYS_REASONING_PROVIDER=openrouter # no OPENROUTER_API_KEY # after LAST30DAYS_REASONING_PROVIDER=openrouter OPENROUTER_API_KEY=sk-or-v1-...
Defensive patterns
Strategy: validation
Validate before calling
if (os.environ.get("LAST30DAYS_REASONING_PROVIDER") or "").lower() == "openrouter":
if not os.environ.get("OPENROUTER_API_KEY"):
raise SystemExit("Set OPENROUTER_API_KEY before selecting the openrouter provider") Type guard
def openrouter_ready(config: dict) -> bool:
provider = (config.get("LAST30DAYS_REASONING_PROVIDER") or "gemini").lower()
return provider != "openrouter" or bool(config.get("OPENROUTER_API_KEY")) Try / catch
try:
runtime, client = resolve_runtime(config, depth)
except RuntimeError as e:
if "OPENROUTER_API_KEY" in str(e):
set_key_via_setup("OPENROUTER_API_KEY") Prevention
- Create the key at openrouter.ai/keys and store it in the loaded .env layer
- Verify gateway/harness processes pass the env var through to the engine
- Smoke-test config loading before long runs
When it happens
Trigger: LAST30DAYS_REASONING_PROVIDER=openrouter with OPENROUTER_API_KEY not set in the environment or ~/.config/last30days/.env; or set in the shell but the engine was launched from another context (cron, harness gateway) without it.
Common situations: OpenRouter key obtained from openrouter.ai/keys but never added to config; per-harness env inheritance gaps (gateway processes stripping env); typo'd variable name.
Related errors
- Gemini selected but no Google API key is configured.
- xAI selected but XAI_API_KEY is not configured.
- No sources are available for this run.
- No X backend is available.
- Unsupported reasoning provider: {provider_name}
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/dbf6f6cad969c98b.
Report an issue: GitHub.