Skip to content

fix(http): fail fast when network is unavailable - #11066

Merged
jdx merged 3 commits into
mainfrom
codex/fail-fast-offline-http
Jul 16, 2026
Merged

jdx merged 3 commits into
mainfrom
codex/fail-fast-offline-http

Conversation

@jdx

@jdx jdx commented Jul 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • treat DNS resolver failures as non-retryable
  • open a process-local circuit after hard DNS or connection failures
  • disable HTTP retries and cap remote-version lookups at 3 seconds under prefer_offline
  • document the fast-path policy and add regression coverage

Root cause

When a fuzzy tool request had no matching installed version, shims and other fast commands had to resolve it remotely. DNS and connection failures were classified as transient, so each endpoint repeated the full timeout and retry schedule. Multiple lookups to the same unavailable origin paid that cost independently.

User impact

Shims, shell activation, and mise x now make one bounded remote-version attempt when cached data is insufficient. Repeated requests to an origin that already failed hard return immediately. Artifact download timeouts remain unchanged.

Context: #4598

Testing

  • mise run test:unit — 1,727 tests passed
  • mise run lint-fix
  • mise run render:schema
  • git diff --check

This pull request was generated by an AI coding assistant.


Note

Medium Risk
Changes sit on the shared HTTP stack and settings used by shims and version resolution, but the new limits and circuit breaker apply only when prefer_offline is active; full install/download paths keep prior retry and timeout behavior.

Overview
Fast commands (shims, shell activation, and anything using prefer_offline) no longer stack long timeouts and HTTP retries when remote version lookups miss cache and the network is down.

Settings now caps fetch_remote_versions_timeout at 3 seconds and forces http_retries to 0 under prefer_offline, with docs updated for fetch_remote_versions_timeout and http_retries. The fetch HTTP client applies that shorter timeout per request at send time (the static client still uses the configured timeout).

In src/http.rs, a process-local circuit records hard DNS/connect failures per origin during prefer_offline and short-circuits later requests with the original cause (without leaking query strings). DNS failures are treated as non-retryable; HTTP→HTTPS fallback still runs when the circuit blocks an http attempt. Sigstore retry config follows the new http_retries() helper.

Unit tests cover prefer-offline retry disabling, fetch timeout clamping, DNS/circuit behavior, and HTTPS fallback when the circuit is open.

Reviewed by Cursor Bugbot for commit 6344514. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added an offline-aware HTTP “circuit breaker” to quickly fail repeat requests to unreachable hosts while preserving the original error.
  • Bug Fixes
    • Improved offline-preferred behavior by capping the remote-versions timeout, reducing the per-request timeout, and disabling HTTP retries for fast commands.
    • Expanded HTTP→HTTPS fallback to also handle circuit-breaker failures.
    • Treated DNS failures as non-transient to avoid unnecessary retries.
  • Documentation
    • Updated settings descriptions to clarify fast-command timeout and retry behavior.
  • Tests
    • Added coverage for circuit behavior, HTTPS fallback, cause preservation, and DNS/cause handling.

Entire-Checkpoint: c6964364bcde
@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Fast commands now cap remote-version timeouts and disable HTTP retries. HTTP requests classify and cache hard connection failures by host, reject subsequent attempts, and support HTTPS fallback. Retry callsites use the new settings accessor, with tests covering offline behavior and circuit handling.

Changes

Offline HTTP behavior

Layer / File(s) Summary
Fast-path settings policy
settings.toml, src/config/settings.rs
Fast commands cap remote-version timeouts at three seconds and return zero HTTP retries when prefer_offline is enabled; documentation describes these semantics.
HTTP retry and host circuit
src/http.rs, src/github/sigstore.rs
HTTP retry callsites use the accessor, while DNS and immediate connection failures mark hosts unavailable and trigger early failures or HTTPS fallback.
Offline HTTP validation
src/http.rs
Tests configure fast-path settings, isolate circuit state, and cover retry suppression, DNS classification, fallback, cause preservation, and disabled-circuit behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • jdx/mise#10482: Introduces the sigstore retry configuration that this change now reads through the normalized settings accessor.

Suggested reviewers: risu729

Poem

I’m a rabbit with packets tucked under my ear,
Fast paths now hop past retries held dear.
Three seconds to wait when caches fall short,
Hard hosts take a rest,
While HTTPS comes forth!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: making HTTP requests fail fast when the network is unavailable.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/http.rs`:
- Around line 618-623: Update send_once_with_https_fallback_with_retry_headers
so its HTTP-to-HTTPS fallback condition also recognizes circuit-broken hosts
from UNAVAILABLE_HTTP_HOSTS, in addition to is_connection_error(&err). Preserve
the existing fallback behavior for connection errors and ensure subsequent
requests to affected http:// URLs still retry via https://.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 97bfc975-9cf6-4b2e-abba-f1e3f584d864

📥 Commits

Reviewing files that changed from the base of the PR and between de81dc8 and e9cb42f.

📒 Files selected for processing (4)
  • settings.toml
  • src/config/settings.rs
  • src/github/sigstore.rs
  • src/http.rs

Comment thread src/http.rs Resolved
@greptile-apps

greptile-apps Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR addresses slow shim and activation paths when the network is unavailable by introducing three coordinated mechanisms: a prefer_offline-gated circuit breaker keyed by origin, DNS failure reclassification as non-transient, and a per-request 3 s timeout cap (plus retry=0) for fast-path commands.

  • Circuit breaker (UNAVAILABLE_HTTP_HOSTS): opened only under prefer_offline on hard DNS or connection failures; both write and read are gated, so slow commands (mise install) are unaffected. HTTP\u2192HTTPS fallback is extended to also trigger when the circuit fires.
  • Settings helpers (http_retries(), configured_fetch_remote_versions_timeout()): cleanly separate the prefer_offline-aware accessors from the raw field, with all existing call sites updated.
  • Tests: cover retry disabling, DNS non-transient classification, circuit open/fallback, credential scrubbing from circuit error text, and circuit bypass outside prefer_offline.

Confidence Score: 5/5

Safe to merge — the circuit and retry changes are strictly scoped to prefer_offline paths; artifact download timeouts and non-prefer_offline behavior are unchanged.

Both the circuit write and read in send_once_inner are gated on prefer_offline(), confirmed by test_circuit_breaker_is_disabled_without_prefer_offline. Credential scrubbing (err.without_url()) prevents secret leakage into the circuit table. The two findings are minor usability nits that do not affect correctness.

No files require special attention; src/http.rs carries the most logic but the circuit gating is thorough and well-tested.

Important Files Changed

Filename Overview
src/http.rs Adds circuit breaker (prefer_offline-gated), DNS non-transient classification, per-request 3s timeout cap for Fetch clients, and HTTPS fallback extension; logic is sound but the timeout hint for Fetch under prefer_offline mentions the wrong knob
src/config/settings.rs Adds http_retries() and configured_fetch_remote_versions_timeout() helpers; the latter is pub rather than pub(crate), which exposes a bypass of the prefer_offline clamping
src/github/sigstore.rs Updates Sigstore retry config to use the new http_retries() accessor; straightforward one-line change, correct
settings.toml Adds docs block to fetch_remote_versions_timeout and extends http_retries description to document prefer_offline fast-path behavior; accurate and helpful

Reviews (3): Last reviewed commit: "fix(http): apply fast timeout per reques..." | Re-trigger Greptile

Comment thread src/http.rs Resolved
Comment thread src/http.rs Resolved
Comment thread src/http.rs Resolved
@github-actions

github-actions Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.7 x -- echo 22.6 ± 2.5 19.5 37.8 1.00
mise x -- echo 23.7 ± 2.3 19.9 58.2 1.05 ± 0.15

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.7 env 22.4 ± 1.3 19.8 27.1 1.02 ± 0.09
mise env 21.9 ± 1.5 18.8 31.0 1.00

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.7 hook-env 23.5 ± 1.2 21.0 30.0 1.04 ± 0.09
mise hook-env 22.5 ± 1.5 18.9 29.5 1.00

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.7 ls 20.1 ± 1.1 17.1 24.3 1.05 ± 0.09
mise ls 19.2 ± 1.2 15.9 23.5 1.00

xtasks/test/perf

Command mise-2026.7.7 mise Variance
install (cached) 184ms 185ms +0%
ls (cached) 69ms 68ms +1%
bin-paths (cached) 78ms 74ms +5%
task-ls (cached) 162ms 158ms +2%

Entire-Checkpoint: 369a52f0edfd

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 424b5bd. Configure here.

Comment thread src/http.rs Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/http.rs`:
- Around line 675-683: Update the circuit-breaker caching in the prefer_offline
hard-failure branch to store the error string after calling
reqwest::Error::without_url(), rather than using err.to_string() directly. Keep
the existing host selection and UNAVAILABLE_HTTP_HOSTS insertion behavior
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 592f0e08-470f-47da-b18d-524b3ef1d812

📥 Commits

Reviewing files that changed from the base of the PR and between e9cb42f and 424b5bd.

📒 Files selected for processing (1)
  • src/http.rs

Comment thread src/http.rs Resolved
Entire-Checkpoint: 832aefbdd3d8
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

@jdx
jdx merged commit 6c59f38 into main Jul 16, 2026
35 checks passed
@jdx
jdx deleted the codex/fail-fast-offline-http branch July 16, 2026 19:02
This was referenced Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant