{"record":{"id":"c9860d58307d83e1","repo":"janhq/jan","slug":"invalid-response-from-server-0","errorCode":null,"errorMessage":"Invalid response from server: {0}","messagePattern":"Invalid response from server: (.+?)","errorType":"exception","errorClass":"UpdateError","httpStatus":null,"severity":"warning","filePath":"src-tauri/src/core/updater/custom_updater.rs","lineNumber":40,"sourceCode":"    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>,\n    #[serde(default)]\n    pub platforms: Option<serde_json::Value>,\n    /// URL to download the update","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/src-tauri/src/core/updater/custom_updater.rs#L22-L58","documentation":"The InvalidResponse variant of UpdateError is returned when the update endpoint responds with a non-2xx HTTP status code. The error message includes both the status code and the response body text, so you can see the server's error detail. This differs from ParseError (2xx but bad body) and RequestFailed (no response at all).","triggerScenarios":"Server returns 404 (endpoint path changed). Server returns 401/403 (HMAC signature rejected or IP blocked). Server returns 500/502/503 (server error, gateway timeout, maintenance). Server returns 429 (rate limited). CDN returns a non-2xx cached error.","commonSituations":"Endpoint URL changed after an infrastructure migration. HMAC signing key mismatch between client and server (JAN_SIGNING_KEY). Rate limiting from too-frequent update checks. Server-side outage or maintenance window. Reverse proxy misconfiguration.","solutions":["Read the status code and body text in the error message to diagnose the server-side issue.","If 401/403, verify the JAN_SIGNING_KEY build-time env var matches the server.","If 429, reduce update check frequency.","If 5xx, wait and retry — the server is temporarily unavailable."],"exampleFix":"# reproduce the request manually to see server response\ncurl -v -H 'Accept: application/json' \\\n  -H 'User-Agent: Jan/1.0.0 (linux; x86_64)' \\\n  https://apps.jan.ai/update-check","handlingStrategy":"try-catch","validationCode":"// In Rust, pre-check endpoint health (simplified)\nasync fn probe_endpoint(url: &str) -> Result<u16, String> {\n    let resp = reqwest::Client::builder()\n        .timeout(Duration::from_secs(5))\n        .build()\n        .map_err(|e| e.to_string())?\n        .get(url)\n        .send()\n        .await\n        .map_err(|e| e.to_string())?;\n    Ok(resp.status().as_u16())\n}","typeGuard":null,"tryCatchPattern":"Err(UpdateError::InvalidResponse(detail)) => {\n    log::warn!(\"Update endpoint returned invalid response: {detail}\");\n    // If it contains '401' or '403', the HMAC key may be wrong\n    // If it contains '5xx', the server is down — try fallback endpoints\n    // If it contains '429', back off before retrying\n}","preventionTips":["Log the full InvalidResponse detail (status code + body) for diagnosis.","If the status is 401/403, verify the JAN_SIGNING_KEY matches the server.","If the status is 5xx, wait and retry — it is transient.","If the status is 429, implement backoff to avoid rate limiting."],"tags":["updater","http-status","response","server-error","authentication"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}