Environment:
- MacBook Air (Apple Silicon, arm64)
- macOS 15.4.1 (Sonoma)
- .NET SDK 9.0.203, .NET Runtime 9.0.4 (osx-arm64)
- No VPN, firewall, or security software interfering
- DNS set to Google (8.8.8.8)
- Azure SDK client code (using
DefaultAzureCredential)
Problem:
When running a .NET app that connects to Azure’s API endpoint (eastus.api.azureml.ms), DNS resolution fails in .NET, but works in the terminal with dig and for other domains in .NET.
Sample output:
[DEBUG] .NET DNS test for eastus.api.azureml.ms
[DEBUG] .NET DNS resolution failed: nodename nor servname provided, or not known
[DEBUG] .NET DNS test for vienna-eastus-ip-ingress-nginx-02.eastus.cloudapp.azure.com
[DEBUG] .NET DNS resolved: 48.211.42.162
[DEBUG] .NET DNS test for www.google.com
[DEBUG] .NET DNS resolved: 142.250.72.100
dig eastus.api.azureml.msreturns a CNAME chain ending in an A record, as expected.- .NET can resolve the final A record and other domains, but not the original Azure CNAME.
Error from Azure SDK:
❌ Error occurred: Retry failed after 2 tries. Retry settings can be adjusted in ClientOptions.Retry or by configuring a custom retry policy in ClientOptions.RetryPolicy. (nodename nor servname provided, or not known (eastus.api.azureml.ms:443))
[DEBUG] Exception Type: System.AggregateException
[DEBUG] Inner Exception: nodename nor servname provided, or not known (eastus.api.azureml.ms:443)
[DEBUG] Inner Exception Type: Azure.RequestFailedException
Question:
Why does .NET on macOS fail to resolve the Azure CNAME (eastus.api.azureml.ms) when system tools and .NET can resolve the final A record and other domains?
What else can I try to get .NET DNS resolution working for this Azure endpoint?
Any help or insight would be greatly appreciated!
Code excerpt:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#nullable disable
using Azure.Identity;
using Azure.Core;
namespace Azure.AI.Projects;
public class Sample_Agent
{
static async Task Main()
{
Console.WriteLine($"Application started at: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
Console.WriteLine("Initializing agent configuration...");
// Use explicit connection string as requested
var connectionString = "<project connection string I scrubbed, format: <HostName>;<AzureSubscriptionId>;<ResourceGroup>;<ProjectName>>";
Console.WriteLine($"[DEBUG] Using connection string: {connectionString.Substring(0, Math.Min(connectionString.Length, 20))}... (masked)");
Console.WriteLine($"[DEBUG] Machine Name: {Environment.MachineName}");
Console.WriteLine($"[DEBUG] OS Version: {Environment.OSVersion}");
Console.WriteLine($"[DEBUG] Current Directory: {Environment.CurrentDirectory}");
try
{
var host = "eastus.api.azureml.ms";
Console.WriteLine($"[DEBUG] .NET DNS test for {host}");
var entry = System.Net.Dns.GetHostEntry(host);
Console.WriteLine($"[DEBUG] .NET DNS resolved: {entry}");
}
catch (Exception ex)
{
Console.WriteLine($"[DEBUG] .NET DNS resolution failed: {ex.Message}");
}
var options = new AIProjectClientOptions();
options.Retry.MaxRetries = 1;
AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential(), options);
try
{
Console.WriteLine("[DEBUG] Attempting to retrieve agent by ID");
Response<Agent> agentResponse = await client.GetAgentAsync("<agent id I scrubbed>");
Agent agent = agentResponse.Value;
Console.WriteLine($"✓ Agent retrieved successfully (ID: {agent.Id})");
// Verify agent in list
Console.WriteLine("\nVerifying agent in list...");
Response<PageableList<Agent>> agentListResponse = await client.GetAgentsAsync();
Console.WriteLine($"✓ Found {agentListResponse.Value.Data.Count} agent(s) in total");
// Step 2: Create a thread
Console.WriteLine("\n=== Creating Thread ===");
Response<AgentThread> threadResponse = await client.CreateThreadAsync();
AgentThread thread = threadResponse.Value;
Console.WriteLine($"✓ Thread created successfully (ID: {thread.Id})");
// Step 3: Add a message
Console.WriteLine("\n=== Adding Message to Thread ===");
string userMessage = "I need to solve the equation `3x + 11 = 14`. Can you help me?";
Console.WriteLine($"User message: {userMessage}");
Response<ThreadMessage> messageResponse = await client.CreateMessageAsync(
thread.Id,
MessageRole.User,
userMessage);
ThreadMessage message = messageResponse.Value;
Console.WriteLine($"✓ Message added successfully (ID: {message.Id})");
// Verify message in thread
Console.WriteLine("\nVerifying message in thread...");
Response<PageableList<ThreadMessage>> messagesListResponse = await client.GetMessagesAsync(thread.Id);
Console.WriteLine($"✓ Found {messagesListResponse.Value.Data.Count} message(s) in thread");
// Step 4: Run the agent
Console.WriteLine("\n=== Starting Agent Run ===");
Response<ThreadRun> runResponse = await client.CreateRunAsync(
thread.Id,
agent.Id,
additionalInstructions: "");
ThreadRun run = runResponse.Value;
Console.WriteLine($"✓ Run initiated (ID: {run.Id})");
// Monitor run progress
int pollCount = 0;
Console.WriteLine("\nMonitoring run progress:");
do
{
pollCount++;
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Status: {runResponse.Value.Status} (Poll #{pollCount})");
await Task.Delay(TimeSpan.FromMilliseconds(500));
runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id);
}
while (runResponse.Value.Status == RunStatus.Queued
|| runResponse.Value.Status == RunStatus.InProgress);
Console.WriteLine($"\n✓ Run completed with status: {runResponse.Value.Status}");
if (runResponse.Value.LastError != null)
{
Console.WriteLine($"⚠ Last error: {runResponse.Value.LastError.Message}");
}
// Get final messages
Console.WriteLine("\n=== Final Message History ===");
Response<PageableList<ThreadMessage>> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id);
IReadOnlyList<ThreadMessage> messages = afterRunMessagesResponse.Value.Data;
Console.WriteLine($"Retrieved {messages.Count} total messages\n");
Console.WriteLine("Message Timeline:");
Console.WriteLine("----------------");
foreach (ThreadMessage threadMessage in messages)
{
Console.WriteLine($"\n[{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss}]");
Console.WriteLine($"Role: {threadMessage.Role}");
Console.WriteLine("Content:");
foreach (MessageContent contentItem in threadMessage.ContentItems)
{
if (contentItem is MessageTextContent textItem)
{
Console.WriteLine($" {textItem.Text}");
}
else if (contentItem is MessageImageFileContent imageFileItem)
{
Console.WriteLine($" <image from ID: {imageFileItem.FileId}>");
}
}
Console.WriteLine("----------------");
}
}
catch (Exception ex)
{
Console.WriteLine($"\n❌ Error occurred: {ex.Message}");
Console.WriteLine($"[DEBUG] Exception Type: {ex.GetType().FullName}");
Console.WriteLine($"[DEBUG] Stack trace: {ex.StackTrace}");
if (ex.InnerException != null)
{
Console.WriteLine($"[DEBUG] Inner Exception: {ex.InnerException.Message}");
Console.WriteLine($"[DEBUG] Inner Exception Type: {ex.InnerException.GetType().FullName}");
Console.WriteLine($"[DEBUG] Inner Exception Stack trace: {ex.InnerException.StackTrace}");
}
if (ex is Azure.RequestFailedException reqEx)
{
Console.WriteLine($"[DEBUG] Azure RequestFailedException Status: {reqEx.Status}");
Console.WriteLine($"[DEBUG] Azure RequestFailedException ErrorCode: {reqEx.ErrorCode}");
}
}
Console.WriteLine($"\nApplication completed at: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
}
}
Guide followed: https://learn.microsoft.com/en-us/azure/ai-services/agents/quickstart?pivots=programming-language-csharp
What I’ve tried:
- Confirmed system DNS works (
digresolves the CNAME chain). - .NET DNS test for
www.google.comand the final A record in the CNAME chain both succeed. - Disabled all VPN, firewall, and security software.
- Used Google DNS (8.8.8.8).
- Checked
/etc/hostsand/etc/resolv.conf. - Running on latest .NET SDK and runtime for arm64.
- No global.json or custom environment variables set.
- Tried both
Dns.GetHostAddressesandDns.GetHostEntry. - Rebooted after all changes.
dig? What results do you receive for both-t Aand-t AAAA?