{"record":{"id":"0c3626749742debe","repo":"janhq/jan","slug":"all-endpoints-failed","errorCode":null,"errorMessage":"All endpoints failed","messagePattern":"All endpoints failed","errorType":"exception","errorClass":"UpdateError","httpStatus":null,"severity":"warning","filePath":"src-tauri/src/core/updater/custom_updater.rs","lineNumber":37,"sourceCode":"/// - In CI: Set JAN_SIGNING_KEY environment variable at build time\n/// - In local dev: Falls back to a test key\nconst SECRET_KEY: &str = match option_env!(\"JAN_SIGNING_KEY\") {\n    Some(key) => key,\n    None => \"local-dev-test-key-not-for-production\",\n};\n\n/// Timeout for HTTP requests\nconst REQUEST_TIMEOUT_SECS: u64 = 30;\n\n#[derive(Debug, Error)]\npub enum UpdateError {\n    #[error(\"HTTP request failed: {0}\")]\n    RequestFailed(#[from] reqwest::Error),\n\n    #[error(\"Failed to parse update response: {0}\")]\n    ParseError(String),\n\n    #[error(\"All endpoints failed\")]\n    AllEndpointsFailed,\n\n    #[error(\"Invalid response from server: {0}\")]\n    InvalidResponse(String),\n\n    #[error(\"No endpoints configured\")]\n    NoEndpointsConfigured,\n}\n\n/// Update information returned by the update check endpoint\n/// Compatible with Tauri's updater format\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct UpdateInfo {\n    pub version: String,\n    #[serde(default)]\n    pub notes: Option<String>,\n    #[serde(default)]\n    pub pub_date: Option<String>,","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/src-tauri/src/core/updater/custom_updater.rs#L19-L55","documentation":"The AllEndpointsFailed variant of UpdateError is returned when every configured update endpoint in the list returned an error (RequestFailed, ParseError, or InvalidResponse). The check_for_updates method iterates endpoints, trying the first with HMAC signing and the rest without, and returns this error only after all have been exhausted. The last individual error is logged per-endpoint but the final return is AllEndpointsFailed.","triggerScenarios":"All endpoints are down or unreachable (total network outage). All endpoints return non-2xx status codes. All endpoints return malformed responses. The primary signed endpoint rejects the HMAC signature AND all fallback endpoints also fail independently.","commonSituations":"Complete network outage during an update check. All endpoints decommissioned during a migration. Corporate firewall blocking all jan.ai domains. System clock wildly wrong causing all TLS certs to appear invalid. DNS server failure affecting all endpoints.","solutions":["Check the per-endpoint warning logs to see which specific error each endpoint returned.","Verify at least one endpoint is reachable: `curl -v <endpoint-url>`.","Check overall network connectivity.","Review tauri.conf.json plugins.updater.endpoints for stale URLs."],"exampleFix":"// enable debug logging to see per-endpoint errors\nRUST_LOG=jan_core::updater=debug ./jan\n\n// then check logs for: \"Endpoint <url> failed: <error>\"","handlingStrategy":"fallback","validationCode":"// Before update check, verify at least one endpoint is configured\nif endpoints.is_empty() {\n    log::info!(\"No update endpoints configured; skipping update check\");\n    return Ok(None);\n}\n\n// Optionally, probe endpoint reachability\nlet reachable = endpoints.iter().filter(|u| reqwest::Client::new().head(u).send().await.is_ok()).count();\nif reachable == 0 {\n    log::warn!(\"No update endpoints are currently reachable\");\n}","typeGuard":null,"tryCatchPattern":"match updater.check_for_updates(endpoints, nonce, version).await {\n    Ok(Some(info)) => { /* offer update */ }\n    Ok(None) => { /* up to date */ }\n    Err(UpdateError::AllEndpointsFailed) => {\n        log::info!(\"All update endpoints failed; skipping update check silently\");\n        // Non-fatal — the app is still usable\n    }\n    Err(other) => { log::warn!(\"Update check error: {other}\"); }\n}","preventionTips":["Treat AllEndpointsFailed as non-fatal — update checks are best-effort.","Enable per-endpoint logging (RUST_LOG=jan_core::updater=debug) to see individual failures.","Configure at least one fallback endpoint for resilience.","Verify endpoint URLs in tauri.conf.json are current."],"tags":["updater","endpoints","network","fallback","all-failed"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}