0

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.ms returns 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 (dig resolves the CNAME chain).
  • .NET DNS test for www.google.com and 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/hosts and /etc/resolv.conf.
  • Running on latest .NET SDK and runtime for arm64.
  • No global.json or custom environment variables set.
  • Tried both Dns.GetHostAddresses and Dns.GetHostEntry.
  • Rebooted after all changes.
4
  • What exact results do you receive from dig? What results do you receive for both -t A and -t AAAA? Commented May 11 at 20:23
  • @grawity_u1686 ty for the response! Commented May 11 at 23:10
  • <<>> DiG 9.10.6 <<>> -t AAAA eastus.api.azureml.ms Got answer: ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21921 flags: qr rd ra QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1 OPT PSEUDOSECTION: EDNS: version: 0, flags: udp: 512 eastus.api.azureml.ms. 3600 IN CNAME vienna-eastus.trafficmanager.net. vienna-eastus.trafficmanager.net. 30 IN CNAME vienna-eastus-ip-ingress-nginx-02.eastus.cloudapp.azure.com. eastus.cloudapp.azure.com. 60 IN SOA ns1-201.azure-dns.com. msnhst.microsoft.com. 10001 900 300 604800 60 SERVER: 8.8.8.8#53(8.8.8.8) MSG SIZE rcvd: 240 Commented May 11 at 23:12
  • -t A eastus.api.azureml.ms Got answer: ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42074 flags: qr rd ra QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 OPT PSEUDOSECTION: EDNS: version: 0, flags: udp: 512 ANSWER SECTION: eastus.api.azureml.ms. 3600 IN CNAME vienna-eastus.trafficmanager.net. vienna-eastus.trafficmanager.net. 30 IN CNAME vienna-eastus-ip-ingress-nginx-01.eastus.cloudapp.azure.com. vienna-eastus-ip-ingress-nginx-01.eastus.cloudapp.azure.com. 10 IN A 48.211.42.131 SERVER: 8.8.8.8#53(8.8.8.8) WHEN: Sun May 11 19:12:56 EDT 2025 MSG SIZE rcvd: 185 Commented May 11 at 23:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.