{"record":{"id":"eeef90586619a7b4","repo":"microsoft/autogen","slug":"failed-to-sync-gallery-from-url","errorCode":null,"errorMessage":"Failed to sync gallery from ${url}","messagePattern":"Failed to sync gallery from (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-studio/frontend/src/components/views/gallery/api.ts","lineNumber":93,"sourceCode":"  }\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":75,"sourceCodeEnd":100,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-studio/frontend/src/components/views/gallery/api.ts#L75-L100","documentation":"TypeError raised by _format_credential when the credential is neither a dict, AzureKeyCredential, nor an AsyncTokenCredential — e.g. a plain string. The Search SDK requires a credential object; this tool deliberately refuses to guess whether a bare string is a key (use the dict form or AzureKeyCredential).","triggerScenarios":"Passing credential=\"my-api-key-string\" or credential=some_unrelated_object to the tool/config; also passing a sync-only TokenCredential (not AsyncTokenCredential) can land here.","commonSituations":"Reusing code from other SDKs where a raw string key is accepted; wrapping keys in custom credential classes; using azure.core.credentials.TokenCredential (sync) where AsyncTokenCredential is expected.","solutions":["Wrap the key: credential={\"api_key\": KEY} or AzureKeyCredential(KEY).","For AAD auth, pass an async-capable credential such as DefaultAzureCredential() (it implements get_token asynchronously and satisfies the protocol).","Never pass the raw string; the tool intentionally rejects it."],"exampleFix":"# before\nconfig = AzureAISearchConfig(endpoint=E, index_name=I, credential=KEY_STRING)\n\n# after\nfrom azure.core.credentials import AzureKeyCredential\nconfig = AzureAISearchConfig(endpoint=E, index_name=I, credential=AzureKeyCredential(KEY_STRING))\n# or credential={\"api_key\": KEY_STRING}","handlingStrategy":"type-guard","validationCode":"def normalize_credential(cred):\n    if isinstance(cred, str):\n        return {\"api_key\": cred}  # or AzureKeyCredential(cred)\n    return cred","typeGuard":"def is_supported_credential(cred) -> bool:\n    if isinstance(cred, dict):\n        return \"api_key\" in cred\n    try:\n        from azure.core.credentials import AzureKeyCredential\n        from azure.core.credentials_async import AsyncTokenCredential\n        return isinstance(cred, (AzureKeyCredential, AsyncTokenCredential))\n    except ImportError:\n        return False","tryCatchPattern":"try:\n    tool = AzureAISearchTool(name=\"search\", config=config)\nexcept TypeError as e:\n    if \"Credential must be\" in str(e):\n        raise TypeError(\"Wrap the key: {'api_key': ...} or AzureKeyCredential(...)\") from e\n    raise","preventionTips":["Never pass a raw string credential; wrap at the boundary where you read secrets.","Use DefaultAzureCredential() for AAD flows — it satisfies the async protocol."],"tags":["python","credentials","type-error","azure-ai-search"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}