{"record":{"id":"ef1bec8c0705dda3","repo":"microsoft/semantic-kernel","slug":"azure-ai-search-tool-definition-must-have-both-in","errorCode":null,"errorMessage":"Azure AI Search tool definition must have both 'index_connection_id' and 'index_name' options set.","messagePattern":"Azure AI Search tool definition must have both 'index_connection_id' and 'index_name' options set\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Agents/AzureAI/Extensions/AgentDefinitionExtensions.cs","lineNumber":233,"sourceCode":"        return null;\n    }\n\n    private static AzureAISearchToolResource? GetAzureAISearchResource(this AgentDefinition agentDefinition)\n    {\n        Verify.NotNull(agentDefinition);\n\n        var azureAISearch = agentDefinition.GetFirstToolDefinition(AzureAISearchType);\n        if (azureAISearch is not null)\n        {\n            string? indexConnectionId = azureAISearch.GetOption<string>(\"index_connection_id\");\n            string? indexName = azureAISearch.GetOption<string>(\"index_name\");\n            if (string.IsNullOrEmpty(indexConnectionId) && string.IsNullOrEmpty(indexName))\n            {\n                return null;\n            }\n            if (string.IsNullOrEmpty(indexConnectionId) || string.IsNullOrEmpty(indexName))\n            {\n                throw new InvalidOperationException(\"Azure AI Search tool definition must have both 'index_connection_id' and 'index_name' options set.\");\n            }\n            int topK = azureAISearch.GetTopK() ?? 5;\n            string filter = azureAISearch.GetFilter() ?? string.Empty;\n            AzureAISearchQueryType? queryType = azureAISearch.GetAzureAISearchQueryType();\n\n            return new AzureAISearchToolResource(indexConnectionId, indexName, topK, filter, queryType);\n        }\n\n        return null;\n    }\n\n    private static AzureAISearchToolDefinition CreateAzureAISearchToolDefinition(AgentToolDefinition tool)\n    {\n        Verify.NotNull(tool);\n\n        return new AzureAISearchToolDefinition();\n    }\n","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Agents/AzureAI/Extensions/AgentDefinitionExtensions.cs#L215-L251","documentation":"Thrown while building an AzureAISearchToolResource from an agent tool definition. The code treats both index_connection_id and index_name being empty as 'skip this tool' (returns null), but if exactly one of the two is set while the other is empty it throws InvalidOperationException. The library requires both fields together because Azure AI Search grounding needs both a connection reference and a target index.","triggerScenarios":"An agent definition includes an azure_ai_search tool whose options set index_connection_id but omit index_name (or vice versa). Passing GetOption<string>(\"index_connection_id\") returns a value while GetOption<string>(\"index_name\") returns null.","commonSituations":"YAML/JSON agent template has a typo in one key name. A template was partially edited. Copy-paste of a search tool config that dropped one field.","solutions":["Provide both 'index_connection_id' and 'index_name' string options on the azure_ai_search tool definition.","If you intend to disable the tool, remove both options (or remove the tool block) so it returns null instead of throwing.","Validate the agent definition file against the expected schema before loading."],"exampleFix":"// before\ntools:\n  - type: azure_ai_search\n    options:\n      index_connection_id: /subscriptions/.../connections/mySearch\n      # index_name missing -> throws 161\n\n// after\ntools:\n  - type: azure_ai_search\n    options:\n      index_connection_id: /subscriptions/.../connections/mySearch\n      index_name: my-docs-index","handlingStrategy":"validation","validationCode":"var search = agentDefinition.GetFirstToolDefinition(\"azure_ai_search\");\nif (search is not null)\n{\n    string? conn = search.GetOption<string>(\"index_connection_id\");\n    string? name = search.GetOption<string>(\"index_name\");\n    if (string.IsNullOrEmpty(conn) ^ string.IsNullOrEmpty(name))\n        throw new InvalidOperationException(\"azure_ai_search needs both index_connection_id and index_name.\");\n}","typeGuard":"static bool IsAzureAISearchComplete(AgentToolDefinition t) =>\n    !(string.IsNullOrEmpty(t.GetOption<string>(\"index_connection_id\")) ^ string.IsNullOrEmpty(t.GetOption<string>(\"index_name\")));","tryCatchPattern":"try { var resource = agentDefinition.GetAzureAISearchToolResource(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"index_connection_id\"))\n{ /* fix the tool definition before retrying */ }","preventionTips":["Treat index_connection_id and index_name as a single required pair in templates.","Add a schema/CI check on agent definition YAML for the azure_ai_search tool."],"tags":["azure-ai-search","validation","agent-tool","configuration"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}