{"record":{"id":"04295a397e241d95","repo":"Graphify-Labs/graphify","slug":"no-llm-backend-configured-set-one-of-gemini-api","errorCode":null,"errorMessage":"No LLM backend configured. Set one of: GEMINI_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY, MOONSHOT_API_KEY, AZURE_OPENAI_API_KEY+AZURE_OPENAI_ENDPOINT, OLLAMA_BASE_URL, or AWS credentials. Pass backend= explicitly to select a provider.","messagePattern":"No LLM backend configured\\. Set one of: GEMINI_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY, MOONSHOT_API_KEY, AZURE_OPENAI_API_KEY\\+AZURE_OPENAI_ENDPOINT, OLLAMA_BASE_URL, or AWS credentials\\. Pass backend= explicitly to select a provider\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"graphify/llm.py","lineNumber":1761,"sourceCode":"    deep_mode: bool = False,\n) -> dict:\n    \"\"\"Extract semantic nodes/edges from a list of files using the given backend.\n\n    Returns dict with nodes, edges, hyperedges, input_tokens, output_tokens.\n    Raises ValueError for unknown backends or when no API key is configured.\n    Raises ImportError if SDK missing.\n\n    Accepts ``str`` paths as well as ``Path``; string entries are coerced up\n    front so downstream helpers (``_partition_semantic_files``, ``_read_files``,\n    ``_build_image_refs``) can rely on ``Path`` semantics (#1386). FileSlice units\n    (from extract_corpus_parallel's oversized-doc slicing, #1369) pass through\n    untouched — Path(FileSlice) would raise (#1397/#1399).\n    \"\"\"\n    files = [f if isinstance(f, (Path, FileSlice)) else Path(f) for f in files]\n    if backend is None:\n        backend = detect_backend()\n        if backend is None:\n            raise ValueError(\n                \"No LLM backend configured. Set one of: GEMINI_API_KEY, ANTHROPIC_API_KEY, \"\n                \"OPENAI_API_KEY, DEEPSEEK_API_KEY, MOONSHOT_API_KEY, \"\n                \"AZURE_OPENAI_API_KEY+AZURE_OPENAI_ENDPOINT, OLLAMA_BASE_URL, \"\n                \"or AWS credentials. Pass backend= explicitly to select a provider.\"\n            )\n    if backend not in BACKENDS:\n        raise ValueError(f\"Unknown backend {backend!r}. Available: {sorted(BACKENDS)}\")\n\n    cfg = BACKENDS[backend]\n    key = api_key or _get_backend_api_key(backend)\n    if not key and backend == \"ollama\":\n        # Ollama ignores auth but the OpenAI client library requires a non-empty\n        # string. Use a placeholder and surface a visible warning so this never\n        # silently routes traffic without the user realising — see F-029.\n        ollama_url = _resolve_ollama_base_url(cfg.get(\"base_url\", \"\"))\n        _validate_ollama_base_url(ollama_url)\n        print(\n            \"[graphify] WARNING: ollama backend selected with no OLLAMA_API_KEY set; \"","sourceCodeStart":1743,"sourceCodeEnd":1779,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/llm.py#L1743-L1779","documentation":"Raised by `extract_files_direct` when `backend=None` and `detect_backend()` also returns None: no backend could be inferred from the environment. graphify discovers backends purely from env vars (GEMINI/ANTHROPIC/OPENAI/DEEPSEEK/MOONSHOT/AZURE keys, AZURE key+endpoint, OLLAMA_BASE_URL, or AWS credentials); with none present and no explicit backend=, it refuses to guess.","triggerScenarios":"Calling `extract_files_direct(files)` with no `backend=` argument in a shell/process where none of the listed env vars are set — fresh machines, subshells that dropped the env, CI runners, containers.","commonSituations":"API key exported in an interactive shell but graphify run from an IDE/service/cron that doesn't inherit it; `.env` file never sourced; typos in variable names (e.g. OPENAI_KEY instead of OPENAI_API_KEY).","solutions":["Export one of the listed variables, e.g. `export OPENAI_API_KEY=...` (or ANTHROPIC_API_KEY, GEMINI_API_KEY, DEEPSEEK_API_KEY, MOONSHOT_API_KEY, AZURE_OPENAI_API_KEY+AZURE_OPENAI_ENDPOINT, OLLAMA_BASE_URL, or AWS creds).","Or pass the backend explicitly: `extract_files_direct(..., backend=\"ollama\", api_key=\"...\")`.","Check for typos and that the variable is visible to the graphify process (`env | grep -i api_key`).","In docker-compose/CI, ensure the env block actually passes the variable into the container."],"exampleFix":"# before\nresult = extract_files_direct(files, root)\n\n# after\nresult = extract_files_direct(files, root, backend=\"openai\", api_key=os.environ[\"OPENAI_API_KEY\"])","handlingStrategy":"validation","validationCode":"from graphify.llm import detect_backend\n\nif detect_backend() is None:\n    raise SystemExit(\"set OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY / \"\n                     \"DEEPSEEK_API_KEY / MOONSHOT_API_KEY / AZURE_OPENAI_* / \"\n                     \"OLLAMA_BASE_URL / AWS creds, or pass backend=\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call `detect_backend()` as a preflight in pipelines instead of relying on the ValueError.","Centralize provider env vars in one sourced env file and verify with `env | grep -E '(API_KEY|OLLAMA_BASE_URL|AWS_)'`.","Pass `backend=` explicitly in scripts so behavior doesn't depend on ambient environment."],"tags":["configuration","environment","backend","api-key"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}