Ollama pull issues

Hello. When I attempt to use or pull (download) models with ollama, I recieve following error (I used placeholders to don’t give specific models):

Error: pull model manifest: Get "``https://hf.co/v2/``<model_author>/<model>/manifests/<version>": net/http: TLS handshake timeout

I assume that the server-side TLS timeout is set to a too low value. It should be minimum 120 seconds.

Plesdr urgently fix it. Thanks

After looking into it, this seems like it may be more of an Ollama (or rather Go) quirk​:thinking::


The important distinction here seems to be who owns the timeout versus why the TLS handshake took too long.

From the error you posted:

pull model manifest: Get "https://hf.co/v2/.../manifests/...": net/http: TLS handshake timeout

I do not think this points to a Hugging Face server-side TLS timeout being set to 10 seconds.

Go’s standard net/http transport has this default:

TLSHandshakeTimeout: 10 * time.Second

and TLSHandshakeTimeout is specifically the maximum time the client waits for a TLS handshake. The net/http: TLS handshake timeout error is generated on that client side when this timer expires.

Ollama’s current manifest-fetch path appears to use an ordinary Go http.Client without replacing that transport in the normal case, so it inherits this behavior. The relevant path is visible in server/images.go.

So I would separate the two questions like this:

  • Where does the 10-second cutoff appear to come from?
    The Ollama/Go client side.

  • Why did the handshake fail to finish within those 10 seconds?
    That is still unknown from this log alone. It could be a transient route problem, packet loss, VPN/proxy/TLS inspection, an IPv4/IPv6 path difference, a regional/CDN edge issue, or something specific to the Ollama process environment.

That said, I would not throw away the motivation behind your “120 seconds” suggestion. It maps quite naturally onto a different design question:

Should the initial manifest request be more tolerant of a transient connection/TLS failure, either through a longer bounded timeout or a small retry/backoff policy?

There is already an open Ollama feature request asking almost exactly that for the initial model-pull phase: #5884 — Extend initial timeout or support retry model pull.

So I think there are really two separable issues here:

  1. diagnosis: why this particular connection spent >10 seconds in TLS;
  2. resilience policy: whether one such transient failure should abort the whole initial manifest pull.

The second can still be worth improving even if the first eventually turns out to be an ISP/router/proxy/CDN-path problem.

The smallest useful test

Before changing timeout values, I would first measure the connection directly. One fairly high-information test is:

curl -sS -o /dev/null \
  --connect-timeout 15 \
  --max-time 20 \
  -w 'code=%{http_code} remote=%{remote_ip} dns=%{time_namelookup} tcp=%{time_connect} tls_done=%{time_appconnect} first_byte=%{time_starttransfer} total=%{time_total}\n' \
  https://huggingface.co/v2/

A 401, 404, etc. is not a failure for this test. The interesting part is whether DNS/TCP/TLS complete promptly.

time_appconnect is the elapsed time from the beginning of the transfer until the TLS connection is established; for an approximate TLS-handshake-only duration, compare it with time_connect. These timing fields are documented in the curl manual.

A useful first-pass decision tree is:

  • If curl itself takes many seconds in TLS or times out:
    look first at the network path: VPN, proxy, TLS inspection, firewall/security software, ISP/routing, IPv4/IPv6, or a localized HF edge/path problem.

  • If curl is consistently fast but Ollama still gets TLS handshake timeout:
    look at the Ollama process itself: Ollama version, whether it is running as a system service/container/app, which proxy variables and certificate store it actually sees, and finally Go-specific TLS behavior.

  • If it is intermittent:
    that makes a small retry/backoff around the initial manifest request especially interesting as a resilience improvement, regardless of which network component caused the transient stall.

I would start there rather than immediately making the timeout 120 seconds, because it tells you which layer you are actually fixing.

Why this appears to be client-side, and why the manifest/model contents are probably not involved yet

There are two useful implementation details here.

First, Go’s DefaultTransport currently includes:

TLSHandshakeTimeout: 10 * time.Second

See the net/http transport source.

The same source also defines TLSHandshakeTimeout as the maximum amount of time to wait for a TLS handshake.

Second, Ollama’s current request path creates an http.Client with redirect behavior but, in the normal path, does not install a replacement transport:

c := &http.Client{
    CheckRedirect: regOpts.CheckRedirect,
}

See Ollama server/images.go.

That means the normal Go default transport is relevant here.

There is another subtle point in the same file: makeRequestWithRetry() has a two-pass structure, but a generic request/network error is returned immediately. The retry is principally used for the HTTP 401 authentication challenge path.

In other words, an initial TLS/network failure is not treated like:

TLS failure
→ wait
→ retry manifest
→ perhaps succeed

but more like:

TLS failure
→ return error
→ pull aborts

That makes an otherwise transient path problem more visible to the user.

Also, the failure stage matters.

The rough sequence is:

DNS
  ↓
TCP connection
  ↓
TLS handshake       <-- your log appears to fail here
  ↓
HTTP registry request
  ↓
manifest response
  ↓
manifest parsing
  ↓
blob/GGUF download
  ↓
digest verification
  ↓
local model loading/runtime

TLS has to be established before the ordinary HTTPS application request/response exchange. The TLS 1.3 protocol structure is described in RFC 8446.

So for this particular error, I would not initially investigate:

  • GGUF corruption;
  • quantization choice;
  • chat templates;
  • GPU support;
  • VRAM;
  • runtime/model architecture support;
  • manifest JSON contents.

Those are downstream layers. They may produce their own errors later, but they do not naturally explain an initial TLS handshake timeout.

A slightly more detailed low-cost diagnostic flow

If the first curl test is abnormal, I would keep the next tests small rather than collecting a huge diagnostic bundle immediately.

1. Compare IPv4 and IPv6

curl -4 -sS -o /dev/null \
  --connect-timeout 15 \
  --max-time 20 \
  -w 'code=%{http_code} remote=%{remote_ip} dns=%{time_namelookup} tcp=%{time_connect} tls_done=%{time_appconnect} total=%{time_total}\n' \
  https://huggingface.co/v2/

and, if the machine actually has usable IPv6:

curl -6 -sS -o /dev/null \
  --connect-timeout 15 \
  --max-time 20 \
  -w 'code=%{http_code} remote=%{remote_ip} dns=%{time_namelookup} tcp=%{time_connect} tls_done=%{time_appconnect} total=%{time_total}\n' \
  https://huggingface.co/v2/

Interpretation:

IPv4 fast, IPv6 slow/failing
    → investigate the IPv6 path

IPv6 fast, IPv4 slow/failing
    → investigate the IPv4 path

both slow/failing
    → broader route/proxy/firewall/edge problem is more plausible

both fast
    → Ollama-process-specific branch becomes more interesting

An immediate curl -6 “couldn’t connect” is not by itself evidence of an HF IPv6 problem; it can simply mean the local machine/network does not have a usable IPv6 route.

2. Compare the two supported HF hostnames separately

The Hugging Face Ollama documentation explicitly says that both hf.co and huggingface.co can be used.

So these are useful as an A/B test:

curl -sS -o /dev/null \
  --connect-timeout 15 \
  --max-time 20 \
  -w 'code=%{http_code} remote=%{remote_ip} tcp=%{time_connect} tls_done=%{time_appconnect} total=%{time_total}\n' \
  https://hf.co/v2/
curl -sS -o /dev/null \
  --connect-timeout 15 \
  --max-time 20 \
  -w 'code=%{http_code} remote=%{remote_ip} tcp=%{time_connect} tls_done=%{time_appconnect} total=%{time_total}\n' \
  https://huggingface.co/v2/

I would not use -L for the first comparison, because following redirects combines multiple connections and makes it harder to see which host’s TLS handshake you are timing.

If one hostname behaves differently, that is useful information.

You can also try the fully qualified model name with Ollama:

ollama pull huggingface.co/<owner>/<repository>:<tag>

but I would treat this as an A/B diagnostic, not a guaranteed fix.

There is currently a separate Ollama issue, #15661, concerning an hf.cohuggingface.co authentication-realm host mismatch.

So if changing the hostname causes the error to change from:

TLS handshake timeout

to something like:

realm host ... does not match original host ...

or another 401/authentication error, that is actually useful: it means you got past the original TLS failure and reached a different layer. I would not merge those two errors into one diagnosis.

3. Try another network, if convenient

A phone hotspot is surprisingly high-information here.

same machine + same Ollama + different network succeeds
    → ISP/router/VPN/corporate-path hypothesis gets much stronger

same failure on unrelated networks
    → client/process/version-specific hypothesis gets stronger

This is often more informative than changing many Ollama settings at once.

If curl is fast but Ollama still fails

This is the branch where I would look closely at how Ollama itself is running.

Go’s DefaultTransport uses proxy settings from:

HTTP_PROXY
HTTPS_PROXY
NO_PROXY

(and their lowercase equivalents).

Meanwhile, Ollama may be running in an environment that is not the same environment as the shell where you ran curl.

Examples:

  • Linux systemd service;
  • macOS application launched outside your shell;
  • Docker container;
  • Windows app/service environment.

The Ollama FAQ documents this distinction. In particular, for model pulls Ollama recommends HTTPS_PROXY, and if the proxy re-signs TLS traffic, its CA certificate needs to be trusted by the relevant system/container.

For Linux/systemd, Ollama’s own documentation shows configuring service environment variables through:

systemctl edit ollama.service
systemctl daemon-reload
systemctl restart ollama

For Docker, the proxy has to reach the container, for example via the container environment, and a custom TLS-inspection CA may also have to be installed in the container image.

This creates an important diagnostic possibility:

curl in interactive shell: succeeds

Ollama daemon:
    has different HTTPS_PROXY / NO_PROXY / CA trust
    ↓
    follows a different effective TLS path
    ↓
    fails

So “curl works” does not necessarily prove that Ollama is using an identical network/TLS environment.

I would avoid solving this by disabling certificate verification. If a corporate proxy performs TLS inspection, installing the appropriate CA in the environment where Ollama actually runs is much safer and much more diagnostic.

Why I think your timeout/retry idea still points at a real design boundary

I think this is the part of your suggestion that is worth preserving.

The registry protocol and the client resilience policy are different concerns.

The registry side exposes operations such as the manifest endpoint:

/v2/<name>/manifests/<reference>

That general protocol shape comes from the OCI Distribution Specification.

But the registry protocol does not inherently require:

client TLS timeout = 10 seconds

or:

retry count = 0

Those are client behavior/resilience choices.

So rather than phrasing the change as:

Hugging Face should raise its TLS timeout to 120 seconds

I would frame the engineering question more like:

Should Ollama make the initial manifest request more resilient to transient connect/TLS failures?

Possible policies include:

A. keep the 10 s handshake timeout, but retry transient network failures

B. use a somewhat longer bounded handshake timeout

C. combine a bounded timeout with a small retry count + backoff/jitter

D. expose an advanced configurable timeout/retry setting

Each has trade-offs.

For example, simply changing:

10 seconds → 120 seconds

can help a genuinely slow handshake, but if packets are black-holed or a middlebox is stuck, it may only turn a 10-second failure into a 120-second failure.

A small retry can sometimes be more useful for transient failures:

attempt 1: unlucky route / transient packet loss
attempt 2: succeeds immediately

but retries should still be bounded, and HTTP/auth errors should not all be retried blindly.

There is already an open Ollama feature request with essentially this concern:

#5884 — Extend initial timeout or support retry model pull

That report is not the same root cause—it shows an initial network i/o timeout rather than your exact TLS error—but the design boundary is very similar: initial model-pull connectivity can fail transiently, and the user asks whether timeout/retry behavior should be configurable or more tolerant.

This also seems distinct from later blob download resilience.

For example, PR #16386 proposes configurable stall handling/resilient chunking for model downloads. That work is in the blob-download phase; it should not be confused with an initial manifest TLS-handshake failure.

So I would keep these as separate failure domains:

manifest/connect/TLS resilience
           ≠
large-blob download/stall resilience
           ≠
GGUF/runtime/model-loading errors

That separation should make both bug reports and fixes easier to reason about.

A small external control I tried

As a sanity check, I also tried the HTTP/TLS layer from a separate Google Colab runtime—not as a reproduction of your machine/network, but as an independent public-network control.

I compared:

curl
Go 1.26.0
Go 1.26.7
hf.co
huggingface.co
default Go TLS settings
PQ-hybrid compatibility toggles

On that Colab path:

  • direct curl over the usable IPv4 path completed TLS quickly;
  • direct huggingface.co with the Go probes succeeded in all 32/32 runs across the tested Go versions/settings;
  • successful Go TLS handshakes were on the order of tens of milliseconds, nowhere near 10 seconds;
  • changing the tested post-quantum TLS compatibility settings did not produce a stable success/failure difference.

There was one isolated connection reset on a redirected hf.co path, but it was not a TLS handshake timeout and did not reproduce.

The Colab runtime did not have a usable IPv6 route, so that test says nothing useful about HF’s IPv6 path.

I would interpret this very narrowly:

I could not reproduce a general “HF + Go 1.26 always hits the TLS timeout” problem from that unrelated network.

It does not rule out anything specific to your:

  • ISP;
  • router;
  • VPN;
  • proxy;
  • TLS-inspection device;
  • local firewall/security software;
  • IPv4/IPv6 path;
  • CDN edge;
  • Ollama service environment.

So I would use this mainly to keep a universal HF/Go incompatibility lower on the list, not to conclude that the problem must be local.

A more exotic Go TLS branch — only if curl is consistently fine

There is one more technically plausible branch, but I would put it after the ordinary network/proxy checks rather than starting here.

Recent Go versions enable post-quantum hybrid TLS key exchanges by default.

The Go 1.24 release notes explicitly note that the larger TLS records involved can expose compatibility bugs in some TLS systems and can result in handshake timeouts. Go provides a compatibility control:

GODEBUG=tlsmlkem=0

Go 1.26 added additional hybrid groups; its release notes document another diagnostic compatibility switch:

GODEBUG=tlssecpmlkem=0

This is interesting if the pattern is specifically:

curl / browser: always fine

Ollama / Go client: repeatedly fails

same network
same destination
same time window

because different TLS implementations can produce different ClientHello layouts/key shares and therefore interact differently with a buggy firewall/proxy/middlebox.

But I would not currently make this the primary explanation:

  • TLS handshake timeout reports in Ollama predate these Go changes;
  • the separate Colab control above did not show a stable PQ-on/PQ-off difference;
  • ordinary routing/proxy/environment explanations are simpler and more common.

If this branch ever becomes worth testing, I would use those GODEBUG switches only as temporary A/B diagnostics on the actual Ollama process—not as a permanent “fix”. They change TLS key-exchange behavior; they do not disable certificate verification.

If this needs to become a reproducible Ollama issue

If the problem persists and you want to turn it into a useful upstream report, I think a very small evidence bundle would be enough.

Something like:

Ollama version:
OS:
native / Docker / WSL / other:
exact pull command:
timestamp + timezone:
proxy/VPN: yes/no

Ollama error:
...

timed curl to https://huggingface.co/v2/:
...

curl -4 result:
...

curl -6 result, if IPv6 is actually available:
...

same command on a different network:
success / same failure / not tested

If curl is fast while Ollama fails, also note whether Ollama is running as:

interactive shell process
systemd service
macOS app
Windows app
Docker container

because that determines which proxy/environment/CA configuration is relevant.

No tokens, proxy passwords, private URLs, or other credentials need to be posted.

That should be enough for someone upstream to distinguish:

network-path problem
vs
service environment problem
vs
Go/TLS-specific problem
vs
retry/resilience design issue

without needing a large diagnostic dump.

So my current read would be:

The 10-second timeout itself looks client-side (Go/Ollama), not like an HF server-side TLS setting. But the log does not tell us why the handshake exceeded 10 seconds. Your underlying resilience concern still seems reasonable; I would just move it to the client-side initial-manifest timeout/retry boundary.

And for the immediate failure, the single timed curl above is probably the cheapest next observation with the highest information gain.

Hello and thanks for the answer.

At the begining, I would like to make a friendly reminder that in normal cases, the most of Your listed possible cause situations don’t apply, as well as possibility to use the curl command (in case of Windows users) doesn’t apply.

As for the other mentioned matters, I think that it may be possibly a result of some missconfiguration.

Many server administrators think that if they shorten the times (handshake, verification, timeout of any kind, etc.) then the server will become more secure (with is a invalid thinking logic).

Many users don’t use VPN, proxy, etc. for the dayly connections

Um… even in an environment where absolutely everything else is working perfectly, unless we first distinguish whether this is Go’s own behavior, nobody can determine whether this is actually something Hugging Face can fix​:sweat_smile:.


I think I may have made the previous explanation too broad, so let me reduce this to the important part.

I am not saying that a Hugging Face server, CDN edge, or other server-side component cannot be misconfigured. It certainly can be.

The important point is that an HTTPS connection does not have one universal “TLS timeout” controlled only by the server administrator.

There can be several independent timers.

A simplified picture is:

Ollama
  |
  v
Go HTTP/TLS client
  |
  |  client-side TLS handshake timer
  |  (Go's normal HTTP transport: 10 seconds)
  |
  v
network
  |
  v
HF / CDN / server
  |
  |  server-side timers may also exist
  |
  v
application

Whichever relevant timer expires first can terminate the operation.

That distinction matters here because Go’s standard HTTP transport really does have:

TLSHandshakeTimeout: 10 * time.Second

See the Go net/http documentation/source: Go net/http DefaultTransport.

And Ollama’s manifest pull goes through its Go HTTP request path; the current implementation can be inspected in Ollama server/images.go.

So when Ollama reports:

net/http: TLS handshake timeout

one thing we can say fairly confidently is:

the Go/Ollama client stopped waiting for the TLS handshake.

But that does not yet answer a second question:

Why had the TLS handshake not completed before that client-side timer expired?

Those are two different questions.

For example, this sequence is completely possible:

something on the server/path responds too slowly
        |
        v
Go waits for the TLS handshake
        |
        v
10 seconds elapse
        |
        v
Go's own client-side timer expires
        |
        v
"net/http: TLS handshake timeout"

In that case, the timer that produced the error is client-side, while the underlying reason for the delay could still be elsewhere.

So identifying the client-side timer is not the same thing as declaring “the server is innocent.”

It is just necessary before we can know where a fix belongs.

Why this distinction is important

Suppose we have three cases.

Case A:
HF/CDN/server itself has a problem
→ an HF-side fix may be appropriate

Case B:
Ollama's client timeout/retry policy is too aggressive
→ this is primarily an Ollama-side design issue

Case C:
server and client are both configured reasonably,
but something in the network path delays or loses the handshake
→ changing either timeout might only mask the underlying problem

All three can eventually present to a Go program as:

net/http: TLS handshake timeout

Without distinguishing them, we do not yet know:

  • who can actually fix the problem;
  • whether increasing a timeout is a fix or only a workaround;
  • whether retry would be better than a much longer timeout;
  • whether this belongs in an HF issue, an Ollama issue, or somewhere else.

That is why I was suggesting a comparison with another client implementation. The particular command is secondary; the purpose is to answer:

Does another HTTP/TLS stack behave differently against the same destination?

A concrete example from completely different software

There is a very useful real-world example in Prometheus’s blackbox_exporter.

The exporter can have an overall probe budget of roughly 120 seconds, but there is an open report where the HTTPS probe still fails after about 10 seconds with:

net/http: TLS handshake timeout

The issue is literally titled:

“net/http: TLS handshake timeout is only 10s and not use probe timeout value”

See Prometheus blackbox_exporter issue #751.

The reported probe starts with approximately:

timeout_seconds=119.5

but fails roughly ten seconds later:

duration_seconds=10.037...
err="... net/http: TLS handshake timeout"

That is a nice demonstration of the layering:

application-level budget
≈ 120 seconds

but inside that application:

Go net/http TLS handshake timer
= 10 seconds

So even though somebody configured the application to allow about two minutes, an internal library-level timer could still terminate one phase after ten seconds.

That is basically the conceptual point I am trying to make here.

The programming language/runtime/library stack can absolutely affect when a network operation times out.

Another example: same machine and server, different client software

There is also an old but very illustrative Terraform report: Terraform issue #15817.

Terraform failed while downloading a provider with:

net/http: TLS handshake timeout

The reporter then entered the same container and requested the same HashiCorp URL using curl.

curl completed the TLS handshake and received:

HTTP/1.1 200 OK

So conceptually:

same container
same destination
same network

Terraform / Go HTTP stack
    → TLS handshake timeout

curl / libcurl
    → successful TLS connection

That does not automatically prove that Go was defective, of course.

What it proves is the more limited and useful point:

Different client stacks can behave differently against the same server.

That is why comparing clients is diagnostic rather than arbitrary.

There are also cases where the visible Go error is client-side but the actual underlying problem turns out to be somewhere else entirely.

For example, HashiCorp published a 2026 Terraform Enterprise troubleshooting case where:

net/http: TLS handshake timeout

was ultimately traced to an incorrect Docker/GCP MTU configuration, not to a server administrator choosing an overly short TLS timeout.

See HashiCorp’s “Failed to install provider - net/http: TLS handshake timeout” article.

So the same visible error can mean:

client timer expired

while the root cause is:

network configuration

That is exactly why the two questions need to remain separate.

About your server-administrator point

I agree with the narrower statement that server-side timeout configuration can be wrong, and that blindly shortening every timeout in the name of “security” is not necessarily a sensible policy.

What I would avoid is jumping from that general observation to:

this error says "TLS handshake timeout"
therefore
the HF server administrator configured a short TLS timeout

because there is another timer we can already identify directly in the software stack: Go’s client-side 10-second TLS handshake timeout.

A useful way to phrase the diagnostic problem is therefore:

1. Who stopped waiting?

For this particular error:

Go/Ollama appears to have stopped waiting.

2. Why did it have to wait that long?

From the error alone:

not yet established

3. Who can fix the underlying problem?

Until #2 is known:

also not yet established

That last point is important.

Even if every ordinary user-visible thing on the machine works perfectly — no VPN, no manually configured proxy, browser works, other downloads work, normal Internet connection — it still does not distinguish these cases:

HF responds unusually slowly to this particular TLS/client behavior

vs.

Go's default timing/policy is unsuitable for this particular connection

vs.

some lower network condition affects this connection without visibly
breaking normal browsing

Those cases require different fixes.

And this is separate from whether Ollama could be more resilient

There is still another point where I think your original concern is useful.

Even after the root cause is separated, Ollama can independently ask:

Should one transient TLS/connect failure during the initial manifest fetch immediately abort the entire model pull?

That is an Ollama resilience-policy question.

There is already an open Ollama request along those lines: Ollama #5884 — Extend initial timeout or support retry model pull.

That issue is not proof that your particular failure has the same root cause. But it does show that the timeout/retry behavior of the initial pull stage is already a recognized design question.

And this is why I would separate:

Root-cause question:
Why did this TLS handshake exceed the client's limit?

from

Resilience question:
Should Ollama retry or tolerate this transient failure better?

Both can be valid at the same time.

For example:

HF/network temporarily stalls
        +
Ollama has no useful retry for that initial failure
        =
user-visible pull failure

Improving the second part can make Ollama more robust even if the first part is ultimately outside Ollama.

Likewise, if the real problem is simply that the Go/Ollama timeout policy is too aggressive for otherwise valid connections, that points even more directly toward the client-side policy.

So I am not trying to rule out a server-side problem.

I am saying something narrower:

Before anyone can conclude that Hugging Face has a timeout setting to fix, we first have to distinguish the Go/Ollama client-side timeout from whatever underlying condition caused it to expire.

Otherwise we may be asking the wrong component to change the wrong timer.

Hello and thanks for such excessive answer. I appreciate it :slightly_smiling_face:

I had send this froendly notiffication, because I had seen that I’m not the only person who has issues with downloading models from the page.

Additionally, I had noticed that this problem doesn’t apply only to Ollama, so I thought I let know so it could become troubleshooted