The Error
Your .NET application tries to connect to Ollama and throws:
System.Net.Http.HttpRequestException: Connection refused (127.0.0.1:11434)
---> System.Net.Sockets.SocketException (111): Connection refused
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
Unlike a 401 or 404, a Connection refused error means the TCP connection never established. The process listening on port 11434 is either not running or not reachable from your application’s network context.
Fixes at a Glance
- Start Ollama — the process is not running; run
ollama serveor launch the desktop app - Fix Docker networking — replace
localhostwithhost.docker.internalwhen running inside a container - Correct the endpoint URL — OllamaSharp uses no
/v1; Semantic Kernel needs/v1 - Migrate from the deprecated preview package — uninstall
Microsoft.Extensions.AI.Ollamaand switch to OllamaSharp 5.x
Root Cause 1: Ollama Is Not Running
The simplest cause. Verify Ollama is running and models are installed:
ollama list # Lists installed models — if this fails, Ollama is not running
ollama serve # Start Ollama server manually
Or launch the Ollama desktop application. Once Ollama is running, you can confirm it is accepting connections by hitting the API directly:
curl http://localhost:11434/api/tags
A successful response returns a JSON object listing your installed models. A Connection refused response means Ollama did not start correctly.
Running local models like Phi-4 with Ollama can dramatically reduce inference costs compared to hosted APIs — but only if Ollama stays running. Consider adding it to your system startup or running it as a service.
Root Cause 2: Docker Networking
This is the most common cause of Connection refused when moving from local development to a containerised environment. Inside a Docker container, localhost and 127.0.0.1 resolve to the container itself, not the host machine where Ollama is running.
// ❌ Wrong — localhost inside Docker refers to the container
var client = new OllamaApiClient(new Uri("http://localhost:11434"));
// ✅ Correct — reach the host machine from Docker Desktop (Windows/Mac)
var client = new OllamaApiClient(new Uri("http://host.docker.internal:11434"));
For Linux Docker hosts where host.docker.internal is not available, use one of these alternatives:
# Option A: use the host's gateway IP (usually 172.17.0.1 on default bridge network)
http://172.17.0.1:11434
# Option B: run the container with host networking (no network isolation)
docker run --network=host your-dotnet-app
In Docker Compose, set the endpoint via environment variable so it is configurable per environment:
services:
api:
image: your-dotnet-app
environment:
- Ollama__BaseUrl=http://host.docker.internal:11434
depends_on:
- ollama
ollama:
image: ollama/ollama
ports:
- "11434:11434"
When Ollama runs as a sibling container (as shown above), replace host.docker.internal with the service name: http://ollama:11434.
Root Cause 3: Wrong Endpoint URL Format
OllamaSharp and Semantic Kernel use different URL paths. Using the wrong path gives Connection refused (if you have the port wrong) or 404 Not Found (if the port is right but the path is wrong). Here is the correct format for each client:
// OllamaSharp — connects to Ollama's native API (NO /v1)
var ollamaClient = new OllamaApiClient(new Uri("http://localhost:11434"));
// Semantic Kernel — uses the OpenAI-compatible endpoint (WITH /v1)
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddOpenAIChatCompletion(
modelId: "phi4-mini",
endpoint: new Uri("http://localhost:11434/v1"),
apiKey: "ollama"); // Any non-empty string; Ollama ignores the key
var kernel = kernelBuilder.Build();
// Microsoft.Extensions.AI via OpenAI-compat — also uses /v1
builder.Services.AddOpenAIChatClient(
modelId: "phi4-mini",
endpoint: new Uri("http://localhost:11434/v1"),
apiKey: "ollama");
The /v1 suffix activates Ollama’s OpenAI-compatible API layer. Without it, requests to the Ollama native API endpoint receive a response, but the JSON format does not match what the OpenAI client library expects, resulting in deserialization errors rather than Connection refused.
Root Cause 4: Deprecated Preview Package Migration
The Microsoft.Extensions.AI.Ollama NuGet package was released as a preview during early 2025 and has since been deprecated. If you are still referencing it, remove it and migrate to OllamaSharp 5.x:
# Remove the deprecated package
dotnet remove package Microsoft.Extensions.AI.Ollama
# Install OllamaSharp
dotnet add package OllamaSharp --version 5.1.0
Update the registration code:
// ❌ Old preview package (deprecated — remove this)
// services.AddOllamaChatClient(new Uri("http://localhost:11434"), "phi4-mini");
// ✅ OllamaSharp 5.x — current approach
builder.Services.AddSingleton(new OllamaApiClient(new Uri("http://localhost:11434")));
builder.Services.AddSingleton<IChatClient>(sp =>
sp.GetRequiredService<OllamaApiClient>().AsChatClient("phi4-mini"));
Note the constructor: new OllamaApiClient(new Uri(...)) — not new OllamaClient(). The type name changed in OllamaSharp 5.x. Using the old constructor name causes a compilation error, not a runtime one, so this is caught at build time rather than at runtime.
With OllamaSharp properly registered, you can resolve IChatClient anywhere in your application and send requests in the standard Microsoft.Extensions.AI format:
public class ChatService(IChatClient chatClient)
{
public async Task<string> AskAsync(string question)
{
var response = await chatClient.GetResponseAsync(question);
return response.Text;
}
}
Fix: Add a Health Check for Ollama
Rather than discovering that Ollama is unreachable when a user makes a request, add an ASP.NET Core health check that detects the problem immediately. This is especially important in containerised deployments where Ollama may not have finished loading the model when your application starts.
using Microsoft.Extensions.Diagnostics.HealthChecks;
public class OllamaHealthCheck : IHealthCheck
{
private readonly HttpClient _httpClient;
private readonly string _ollamaUrl;
public OllamaHealthCheck(IHttpClientFactory factory, IConfiguration config)
{
_httpClient = factory.CreateClient();
_ollamaUrl = config["Ollama:BaseUrl"] ?? "http://localhost:11434";
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken ct = default)
{
try
{
var response = await _httpClient.GetAsync(
$"{_ollamaUrl}/api/tags", ct);
return response.IsSuccessStatusCode
? HealthCheckResult.Healthy("Ollama is running")
: HealthCheckResult.Degraded($"Ollama returned {response.StatusCode}");
}
catch (HttpRequestException)
{
return HealthCheckResult.Unhealthy("Ollama is not reachable");
}
}
}
Register the health check and expose the endpoint in Program.cs:
builder.Services.AddHttpClient();
builder.Services.AddHealthChecks()
.AddCheck<OllamaHealthCheck>("ollama");
var app = builder.Build();
app.MapHealthChecks("/health");
With this in place, GET /health returns a Healthy or Unhealthy status that Kubernetes liveness probes, Docker health checks, and load balancers can act on. You can also add a readiness probe that waits until Ollama is healthy before accepting traffic:
# kubernetes deployment excerpt
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
Running local AI with Ollama reduces API costs significantly compared to hosted services, but it introduces an operational dependency that the health check makes visible.
Quick Diagnostic Checklist
If you are still getting Connection refused after working through the fixes above, run through this checklist:
| Check | Command | Expected |
|---|---|---|
| Ollama running | ollama list | Shows model list |
| Port open | curl http://localhost:11434/api/tags | JSON response |
| From Docker | curl http://host.docker.internal:11434/api/tags | JSON response |
| OllamaSharp URL | No /v1 suffix | http://localhost:11434 |
| SK/MEA URL | With /v1 suffix | http://localhost:11434/v1 |
| Package | dotnet list package | OllamaSharp 5.x present |
Further Reading
- Ollama documentation
- OllamaSharp on NuGet
- University: Running Phi-4 Locally in C# — Ollama and ONNX
- Workshop: Build a Local AI App with Ollama, Semantic Kernel, and .NET Aspire