{"record":{"id":"f920da8a883b1c4f","repo":"microsoft/autogen","slug":"failed-to-delete-gallery","errorCode":null,"errorMessage":"Failed to delete gallery","messagePattern":"Failed to delete gallery","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-studio/frontend/src/components/views/gallery/api.ts","lineNumber":87,"sourceCode":"      }\n    );\n    const data = await response.json();\n    if (!data.status)\n      throw new Error(data.message || \"Failed to update gallery\");\n    return data.data;\n  }\n\n  async deleteGallery(galleryId: number, userId: string): Promise<void> {\n    const response = await fetch(\n      `${this.getBaseUrl()}/gallery/${galleryId}?user_id=${userId}`,\n      {\n        method: \"DELETE\",\n        headers: this.getHeaders(),\n      }\n    );\n    const data = await response.json();\n    if (!data.status)\n      throw new Error(data.message || \"Failed to delete gallery\");\n  }\n\n  async syncGallery(url: string): Promise<Gallery> {\n    const response = await fetch(url);\n    if (!response.ok) {\n      throw new Error(`Failed to sync gallery from ${url}`);\n    }\n    return await response.json();\n  }\n}\n\nexport const galleryAPI = new GalleryAPI();\n","sourceCodeStart":69,"sourceCodeEnd":100,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-studio/frontend/src/components/views/gallery/api.ts#L69-L100","documentation":"Raised by the credential normalizer (_format_credential) when a dict credential is passed but has no 'api_key' key. Dict is the convenience form for key auth — {'api_key': '<value>'} — and any other shape (e.g. {'key': ...}, {'apiKey': ...}) is rejected.","triggerScenarios":"Passing credential={'key': '...'} or {'apiKey': '...'} or an unrelated dict (e.g. a loaded JSON settings blob) to the AzureAISearchTool constructor or config.","commonSituations":"Loading credentials from env/settings files whose key naming differs (apiKey vs api_key); passing the entire secrets dict instead of the single entry; assuming arbitrary keys are forwarded to the SDK.","solutions":["Rename the dict key to 'api_key': credential={\"api_key\": os.environ['AZURE_SEARCH_ADMIN_KEY']}.","Or construct a real credential object: AzureKeyCredential(value) / an AsyncTokenCredential implementation and pass that instead of a dict."],"exampleFix":"# before\nconfig = AzureAISearchConfig(endpoint=E, index_name=I, credential={\"apiKey\": KEY})\n\n# after\nconfig = AzureAISearchConfig(endpoint=E, index_name=I, credential={\"api_key\": KEY})","handlingStrategy":"type-guard","validationCode":"def is_valid_credential_dict(cred) -> bool:\n    return isinstance(cred, dict) and \"api_key\" in cred and bool(cred[\"api_key\"])","typeGuard":"from typing import Any\n\ndef is_search_credential(cred: Any) -> bool:\n    if isinstance(cred, dict):\n        return \"api_key\" in cred\n    from azure.core.credentials import AzureKeyCredential\n    from azure.core.credentials_async import AsyncTokenCredential\n    return isinstance(cred, (AzureKeyCredential, AsyncTokenCredential))","tryCatchPattern":"try:\n    tool = AzureAISearchTool(name=\"search\", config=config)\nexcept ValueError as e:\n    if \"api_key\" in str(e):\n        config.credential = {\"api_key\": os.environ[\"AZURE_SEARCH_ADMIN_KEY\"]}\n        tool = AzureAISearchTool(name=\"search\", config=config)\n    else:\n        raise","preventionTips":["Standardize on the {'api_key': ...} dict shape across your codebase.","Load credentials from one helper that always returns the canonical form."],"tags":["python","configuration","credentials","azure-ai-search"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}