janhq/jan · error · UpdateError
Failed to parse update response: {0}
Error message
Failed to parse update response: {0} What it means
The ParseError variant of UpdateError is returned when the update endpoint responded with HTTP 200 but the response body could not be deserialized into the UpdateInfo struct (version is required; notes, pub_date, platforms, url, signature are optional). This means the server returned valid JSON that is missing the required version field, or returned non-JSON content despite a 200 status.
Source
Thrown at src-tauri/src/core/updater/custom_updater.rs:34
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
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)]
pub struct UpdateInfo {
pub version: String,
#[serde(default)]View on GitHub (pinned to fad3f12a14)
Solutions
- Inspect the raw response body from the endpoint to see what was actually returned.
- Ensure the server returns at minimum `{"version": "x.y.z"}`.
- Check for CDN caching of an old or error response.
- Verify the endpoint URL has not changed and still serves the update manifest.
Example fix
# check what the endpoint actually returns
curl -s https://apps.jan.ai/update-check | jq .
# expected shape:
{"version": "1.2.3", "url": "...", "notes": "..."} Defensive patterns
Strategy: validation
Validate before calling
// Validate the response shape before relying on it
function isValidUpdateInfo(data: unknown): data is { version: string } {
return typeof data === 'object' && data !== null &&
typeof (data as any).version === 'string' &&
(data as any).version.length > 0;
}
// Or in Rust, use a lenient deserializer:
fn try_parse_update(body: &str) -> Result<UpdateInfo, UpdateError> {
let v: serde_json::Value = serde_json::from_str(body)
.map_err(|e| UpdateError::ParseError(e.to_string()))?;
let version = v.get("version").and_then(|s| s.as_str())
.ok_or_else(|| UpdateError::ParseError("missing 'version' field".into()))?;
Ok(UpdateInfo { version: version.to_string(), /* ... */ })
} Type guard
function isUpdateInfo(v: unknown): v is { version: string; url?: string } {
return typeof v === 'object' && v !== null &&
typeof (v as Record<string, unknown>).version === 'string';
} Try / catch
Err(UpdateError::ParseError(msg)) => {
log::warn!("Update endpoint returned unparseable response: {msg}");
// Try the next fallback endpoint, or skip this update check
} Prevention
- Validate the response shape before deserializing — check for the 'version' field.
- Log the raw response body when parsing fails so the server-side issue is visible.
- Coordinate response schema with the update endpoint maintainer.
- Use lenient deserialization with serde defaults for optional fields.
When it happens
Trigger: Server returns 200 with an empty body. Server returns JSON missing the required 'version' field. Server returns HTML (e.g. a CDN error page) with a 200 status. Server returns a JSON array instead of the expected object. Schema drift where the server changed its response format.
Common situations: CDN serving a cached error page with 200 status. Endpoint returning a different JSON schema after an API change. Misconfigured reverse proxy returning HTML error page with wrong status. Server returning `{}` (empty object) with no version.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid response from server: {0}
- HTTP request failed: {0}
- All endpoints failed
- No endpoints configured
- No update available
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/c90117b2fe17da63.
Report an issue: GitHub.