{"record":{"id":"b190266a2f364d03","repo":"BerriAI/litellm","slug":"prompt-prompt-prompt-id-already-exists","errorCode":null,"errorMessage":"Prompt '{prompt.prompt_id}' already exists","messagePattern":"Prompt '(.+?)' already exists","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"error","filePath":"cookbook/mock_prompt_management_server/mock_prompt_management_server.py","lineNumber":343,"sourceCode":"            \"prompt_variables\": {var: f\"<{var}_value>\" for var in variables},\n        },\n    }\n\n\n@app.post(\"/prompts\")\nasync def create_prompt(\n    prompt: PromptResponse, authorization: Optional[str] = Header(None)\n):\n    \"\"\"\n    Create a new prompt (convenience endpoint for testing).\n\n    This is NOT part of the LiteLLM spec - it's just for testing purposes.\n    \"\"\"\n    # Verify authentication\n    verify_api_key(authorization)\n\n    if prompt.prompt_id in PROMPTS_DB:\n        raise HTTPException(\n            status_code=status.HTTP_409_CONFLICT,\n            detail=f\"Prompt '{prompt.prompt_id}' already exists\",\n        )\n\n    PROMPTS_DB[prompt.prompt_id] = prompt.dict()\n\n    return {\n        \"status\": \"created\",\n        \"prompt_id\": prompt.prompt_id,\n        \"message\": \"Prompt created successfully (in-memory only)\",\n    }\n\n\n# ============================================================================\n# Main\n# ============================================================================\n\nif __name__ == \"__main__\":","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/cookbook/mock_prompt_management_server/mock_prompt_management_server.py#L325-L361","documentation":"The async-client type guard on the retrieve path, and stricter than the other fine-tuning guards: it accepts only AsyncOpenAI - not AsyncAzureOpenAI. When _is_async=True and the resolved client is anything else (sync OpenAI, or even an Azure async client), this ValueError is raised before the awaited retrieve call. It exists because the subsequent code casts directly to OpenAI's retrieve API.","triggerScenarios":"Calling the async retrieve path with a synchronous OpenAI client, or with an AsyncAzureOpenAI client (which this path does not accept), or when a non-async client is resolved from the environment.","commonSituations":"Porting sync retrieval code to async without swapping client classes; Azure fine-tuning users hitting the async path that only supports the first-party OpenAI async client; shared client factories returning the wrong class.","solutions":["Pass client=AsyncOpenAI(api_key=...) explicitly for async retrieve.","Azure users: use the sync retrieve_fine_tuning_job() or route through the Azure-specific fine-tuning path.","If no custom client is needed, rely on OPENAI_API_KEY so litellm constructs the correct async client."],"exampleFix":"# before\njob = await litellm.aretrieve_fine_tuning_job(\"ftjob-abc\", client=OpenAI())\n\n# after\njob = await litellm.aretrieve_fine_tuning_job(\"ftjob-abc\", client=AsyncOpenAI())","handlingStrategy":"type-guard","validationCode":"from openai import AsyncOpenAI\n\ndef is_first_party_async_client(client: object) -> bool:\n    # stricter than other paths: AsyncAzureOpenAI is NOT accepted here\n    return type(client) is AsyncOpenAI","typeGuard":"from openai import AsyncOpenAI\n\ndef is_usable_async_retrieve_client(client: object) -> bool:\n    return isinstance(client, AsyncOpenAI)","tryCatchPattern":"try:\n    job = await litellm.aretrieve_fine_tuning_job(jid, client=client)\nexcept ValueError as e:\n    if \"AsyncOpenAI\" in str(e):\n        from openai import AsyncOpenAI\n        job = await litellm.aretrieve_fine_tuning_job(jid, client=AsyncOpenAI(api_key=key))\n    else:\n        raise","preventionTips":["Azure users: use the sync retrieve path or Azure-specific handlers; async retrieve accepts only AsyncOpenAI.","Centralize client construction so the correct class is passed per operation."],"tags":["openai","fine-tuning","async","type-mismatch","litellm"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}