jdx/mise · error

HTTP download timed out after

Error message

HTTP download timed out after {} for {} (attempt {}, {} bytes received; change with `http_download_timeout` or env `MISE_HTTP_DOWNLOAD_TIMEOUT`)

What it means

mise's HTTP downloader enforces a total timeout per download attempt (configurable via the `http_download_timeout` setting / `MISE_HTTP_DOWNLOAD_TIMEOUT` env). When a transfer exceeds it, the partial download is validated/handled and this error reports the elapsed timeout, URL, attempt number, and bytes received so far.

Solutions

  1. Increase the timeout: set `http_download_timeout` in settings or export MISE_HTTP_DOWNLOAD_TIMEOUT (e.g. to a larger duration) and retry.
  2. Retry the download — it resumes from the validated partial instead of starting over.
  3. Check network/proxy throughput; try a different mirror or network if transfers stall repeatedly.

Example fix

// before
$ mise install node@22
// after (allow longer downloads)
$ MISE_HTTP_DOWNLOAD_TIMEOUT=30m mise install node@22
// or in settings.toml
[settings]
http_download_timeout = "30m"
Defensive patterns

Strategy: retry

Validate before calling

[ -n "$MISE_HTTP_DOWNLOAD_TIMEOUT" ] && echo "timeout: $MISE_HTTP_DOWNLOAD_TIMEOUT" || echo "using default; large downloads may need more"

Try / catch

for i in 1 2 3; do
  MISE_HTTP_DOWNLOAD_TIMEOUT=30m mise install node@22 && break
  echo "download timed out (attempt $i); retrying"
done

Prevention

When it happens

Trigger: Downloading a large artifact over a slow or stalled connection where total elapsed time exceeds the configured http_download_timeout; a hung server that stops sending data mid-transfer.

Common situations: Large tool archives on slow corporate networks or flaky Wi-Fi; proxies throttling long transfers; CI runners with constrained bandwidth hitting the default timeout.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/9a640aed7fbc994e. Report an issue: GitHub.

Appendix: source

Thrown at src/http.rs:1048

            let partial = partial.clone();
            async move {
                attempt.fetch_add(1, Ordering::Relaxed);
                bytes_received.store(0, Ordering::Relaxed);
                self.download_file_attempt(request_url, headers, &partial, pr, &bytes_received)
                    .await
            }
        });

        let metadata = match tokio::time::timeout(total_timeout, download).await {
            Ok(result) => result?,
            Err(_) => {
                // A timeout cancels the transfer future before its normal cleanup
                // runs. Loading the sidecar removes an unvalidated partial while
                // preserving a resumable one.
                if let Err(err) = partial.load() {
                    debug!("failed to validate partial download after timeout: {err:#}");
                }
                bail!(
                    "HTTP download timed out after {} for {} (attempt {}, {} bytes received; change with `http_download_timeout` or env `MISE_HTTP_DOWNLOAD_TIMEOUT`)",
                    format_duration(total_timeout),
                    url,
                    attempt.load(Ordering::Relaxed),
                    bytes_received.load(Ordering::Relaxed),
                )
            }
        };

        // Complete the atomic rename after the cancellable transfer budget. A
        // blocking task cannot be cancelled once it starts, so keeping it out
        // of `timeout` prevents us from returning an error while it can still
        // install the destination in the background.
        let path = path.to_path_buf();
        tokio::task::spawn_blocking(move || partial.persist(&path)).await??;
        Ok(metadata)
    }

View on GitHub (pinned to 533346cc37)