{"record":{"id":"3ed87c234785ee8a","repo":"BerriAI/litellm","slug":"access-denied-to-prompt-version-prompt-version-i","errorCode":null,"errorMessage":"Access denied to prompt version '{prompt_version_id}'. Check your Arize Phoenix permissions.","messagePattern":"Access denied to prompt version '(.+?)'\\. Check your Arize Phoenix permissions\\.","errorType":"exception","errorClass":"Exception","httpStatus":403,"severity":"error","filePath":"litellm/integrations/arize/arize_phoenix_client.py","lineNumber":84,"sourceCode":"        safe_id: Final = _sanitize_id(prompt_version_id)\n        url: Final = f\"{self.api_base}/v1/prompt_versions/{safe_id}\"\n\n        try:\n            # Use the underlying httpx client directly to avoid query param extraction\n            response = self.http_handler.get(url, headers=self.headers)\n            response.raise_for_status()\n\n            data: Final = response.json()\n            return data.get(\"data\")\n\n        except Exception as e:\n            # Check if it's an HTTP error\n            response = getattr(e, \"response\", None)\n            if response is not None and hasattr(response, \"status_code\"):\n                if response.status_code == 404:\n                    return None\n                elif response.status_code == 403:\n                    raise Exception(\n                        f\"Access denied to prompt version '{prompt_version_id}'. Check your Arize Phoenix permissions.\"\n                    )\n                elif response.status_code == 401:\n                    raise Exception(\"Authentication failed. Check your Arize Phoenix API key and permissions.\")\n                else:\n                    raise Exception(f\"Failed to fetch prompt version '{prompt_version_id}': {e}\")\n            else:\n                raise Exception(f\"Error fetching prompt version '{prompt_version_id}': {e}\")\n\n    def test_connection(self) -> bool:\n        \"\"\"\n        Test the connection to the Arize Phoenix API.\n\n        Returns:\n            True if connection is successful, False otherwise\n        \"\"\"\n        try:\n            # Try to access the prompt_versions endpoint to test connection","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/arize/arize_phoenix_client.py#L66-L102","documentation":"When ArizePhoenixClient.get_prompt_version receives HTTP 403 from the Phoenix API, it converts the httpx error into this explicit Exception: the API key authenticated successfully but the token's role/workspace lacks permission to read that prompt version. Access control on Phoenix Cloud is per-workspace, so a valid key for the wrong workspace yields 403.","triggerScenarios":"Loading a prompt whose prompt_version_id belongs to a different Phoenix workspace or a private prompt your service account cannot read; using a viewer-role API key against a restricted prompt; cross-org access on Phoenix Cloud.","commonSituations":"Key generated in workspace A while the prompt lives in workspace B; rotating to a least-privilege service key that lacks prompt read scope; prompting against an org's private prompt set with a personal key from another org.","solutions":["In the Phoenix UI, open the prompt and confirm which workspace it belongs to; regenerate/use an API key from that exact workspace","Grant the key's role read access to prompts, or switch to a key with member/admin role for that workspace","Verify independently with curl: `curl -H \"Authorization: Bearer $PHOENIX_API_KEY\" <api_base>/prompt_versions/<id>` — 403 confirms permissions, 401 would confirm auth"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Pre-flight the exact read before wiring the prompt into serving paths\nimport httpx, os\n\nresp = httpx.get(\n    f\"{api_base}/prompt_versions/{prompt_version_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['PHOENIX_API_KEY']}\"},\n    timeout=5,\n)\nif resp.status_code == 403:\n    raise SystemExit(\"Key lacks access to this prompt — check workspace/role in Phoenix\")","typeGuard":null,"tryCatchPattern":"try:\n    manager.compile(prompt_id=prompt_id, prompt_variables=vars)\nexcept Exception as e:\n    msg = str(e)\n    if \"Access denied\" in msg:\n        # permissions issue: fail loudly at config time, do not retry — fix workspace/role\n        raise PermissionError(f\"Phoenix key cannot read {prompt_id}: wrong workspace or role\") from e\n    raise","preventionTips":["Use one API key per Phoenix workspace and store the workspace ID alongside it in config","Grant service keys explicit prompt-read access and verify with a preflight GET during deploy"],"tags":["arize-phoenix","authorization","http-403","permissions","prompts"],"backgroundTag":"http-403-forbidden","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}