janhq/jan · error · UpdateError

HTTP request failed

Error message

HTTP request failed: {0}

What it means

UpdateError::RequestFailed wraps a reqwest::Error (via #[from]) whenever the custom updater's HTTP request to a version/check endpoint fails. The message renders as 'HTTP request failed: <reqwest detail>'.

Solutions

  1. Check network connectivity and whether the update endpoint is reachable
  2. Verify the endpoint URL and any proxy configuration (HTTP_PROXY/HTTPS_PROXY)
  3. Retry the update check; the updater iterates endpoints so a mirror may work
  4. Increase REQUEST_TIMEOUT_SECS if 30s is too short for your environment

Example fix

// before
const REQUEST_TIMEOUT_SECS: u64 = 30;
// after
const REQUEST_TIMEOUT_SECS: u64 = 60; // tolerate slow networks
Defensive patterns

Strategy: retry

Validate before calling

const reachable = await fetch(endpoint, { method: 'HEAD', signal: AbortSignal.timeout(5000) }).then(r => r.ok).catch(() => false);
if (!reachable) throw new Error('update endpoint unreachable, check network');

Try / catch

match updater.check() {
    Err(UpdateError::RequestFailed(e)) if e.is_timeout() || e.is_connect() => {
        // exponential backoff retry, max 3 attempts
    }
    other => other?,
}

Prevention

When it happens

Trigger: custom_updater issues a reqwest client request with REQUEST_TIMEOUT_SECS=30 and the connection cannot be established, DNS fails, TLS fails, or the request exceeds the timeout.

Common situations: Offline machine or corporate proxy blocking the update server, DNS misconfiguration, update endpoint temporarily down, or slow networks tripping the 30s timeout.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/e2c01fd0539b5612. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/core/updater/custom_updater.rs:31

use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::time::Duration;
use thiserror::Error;

/// Secret key for HMAC signature
/// - In CI: Set JAN_SIGNING_KEY environment variable at build time
/// - In local dev: Falls back to a test key
pub(crate) const SECRET_KEY: &str = match option_env!("JAN_SIGNING_KEY") {
    Some(key) => key,
    None => "local-dev-test-key-not-for-production",
};

/// Timeout for HTTP requests
const REQUEST_TIMEOUT_SECS: u64 = 30;

#[derive(Debug, Error)]
pub enum UpdateError {
    #[error("HTTP request failed: {0}")]
    RequestFailed(#[from] reqwest::Error),

    #[error("Failed to parse update response: {0}")]
    ParseError(String),

    #[error("All endpoints failed")]
    AllEndpointsFailed,

    #[error("Invalid response from server: {0}")]
    InvalidResponse(String),

    #[error("No endpoints configured")]
    NoEndpointsConfigured,
}

/// Update information returned by the update check endpoint
/// Compatible with Tauri's updater format
#[derive(Debug, Clone, Serialize, Deserialize)]

View on GitHub (pinned to 7205d770c1)