{"record":{"id":"7076db270a7ccc4f","repo":"Graphify-Labs/graphify","slug":"no-api-key-for-backend-backend-set-format-b","errorCode":null,"errorMessage":"No API key for backend '{backend}'. Set {_format_backend_env_keys(backend)} or pass api_key=.","messagePattern":"No API key for backend '(.+?)'\\. Set (.+?) or pass api_key=\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"graphify/llm.py","lineNumber":1786,"sourceCode":"        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; \"\n            f\"sending corpus to {ollama_url}. Set OLLAMA_API_KEY (any non-empty value) \"\n            \"to suppress this warning.\",\n            file=sys.stderr,\n        )\n        key = \"ollama\"\n    if not key and backend not in (\"bedrock\", \"claude-cli\"):\n        raise ValueError(\n            f\"No API key for backend '{backend}'. \"\n            f\"Set {_format_backend_env_keys(backend)} or pass api_key=.\"\n        )\n    mdl = model or _default_model_for_backend(backend)\n    # Separate raster images from text-like files. Text goes through _read_files\n    # as before; images become structured refs the backend renders as pixels\n    # (vision backends) or as a text reference node (everything else).\n    text_files, image_files = _partition_semantic_files(files)\n    user_msg = _read_files(text_files, root)\n    vision = _backend_supports_vision(backend)\n    # Only base64 (inline) vision backends need the bytes loaded + size-capped;\n    # path-based backends (claude-cli) and non-vision backends do not.\n    read_bytes = vision and backend not in _PATH_IMAGE_BACKENDS\n    image_refs = _build_image_refs(image_files, root, read_bytes=read_bytes) if image_files else []\n    if image_refs and not vision:\n        image_refs = _strip_pixels(image_refs)\n    max_out = _resolve_max_tokens(cfg.get(\"max_tokens\", 8192))\n","sourceCodeStart":1768,"sourceCodeEnd":1804,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/llm.py#L1768-L1804","documentation":"Raised by `extract_files_direct` after backend resolution when no API key is available: neither the `api_key=` parameter nor `_get_backend_api_key(backend)` (env-var lookup) produced a value. `bedrock` (AWS credential chain) and `claude-cli` (CLI's own auth) are exempt; `ollama` gets a placeholder key with a warning instead (F-029). Every other backend needs an explicit key.","triggerScenarios":"Selecting a key-based backend (gemini, openai, kimi, deepseek, moonshot, claude, azure) with its env var unset and no `api_key=` passed — e.g. AZURE_OPENAI_API_KEY missing while AZURE_OPENAI_ENDPOINT is set.","commonSituations":"Env var present in the login shell but not in the tool's process (IDE, cron, docker); key set for one provider but `backend=` names another; expired/rotated key deleted from the environment; `.env` not loaded.","solutions":["Set the env var named by `_format_backend_env_keys(backend)` (e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, AZURE_OPENAI_API_KEY) in the process running graphify.","Or pass `api_key=` directly to `extract_files_direct`.","Verify the variable name matches the backend you selected — a Gemini key won't satisfy the openai backend.","For Ollama the warning (not error) path applies; set OLLAMA_API_KEY to any non-empty value to silence it."],"exampleFix":"# before\nextract_files_direct(files, root, backend=\"openai\")  # OPENAI_API_KEY unset\n\n# after\nextract_files_direct(files, root, backend=\"openai\", api_key=os.environ[\"OPENAI_API_KEY\"])","handlingStrategy":"validation","validationCode":"from graphify.llm import _get_backend_api_key, BACKENDS\n\ndef backend_has_credentials(name: str) -> bool:\n    if name in (\"bedrock\", \"claude-cli\"):\n        return True\n    if name == \"ollama\":\n        return True  # placeholder key path\n    return bool(_get_backend_api_key(name))\n\nif not backend_has_credentials(\"openai\"):\n    raise SystemExit(\"export OPENAI_API_KEY or pass api_key=\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass `api_key=` explicitly in code rather than relying on ambient env vars.","Ensure the env var matches the backend actually selected (a GEMINI key won't authorize the openai backend).","Check credentials in the same process context (IDE/service/container) that runs graphify."],"tags":["configuration","api-key","environment","backend"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}