{"record":{"id":"bf05f9ed177bac21","repo":"gitbutlerapp/gitbutler","slug":"server-returned-error-e","errorCode":null,"errorMessage":"Server returned error: {e}","messagePattern":"Server returned error: (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/but-update/src/check.rs","lineNumber":127,"sourceCode":"        .build()?;\n\n    let url = url_override.unwrap_or(UPDATES_CHECK_URL).to_string();\n\n    let result = std::thread::spawn(move || -> anyhow::Result<CheckUpdateStatus> {\n        let runtime = tokio::runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .map_err(|e| anyhow::anyhow!(\"Failed to create runtime: {e}\"))?;\n\n        runtime.block_on(async {\n            let response = client\n                .post(url)\n                .json(&request_body)\n                .send()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"Request failed: {e}\"))?\n                .error_for_status()\n                .map_err(|e| anyhow::anyhow!(\"Server returned error: {e}\"))?;\n\n            let update_info = response\n                .json::<CheckUpdateStatus>()\n                .await\n                .map_err(|e| anyhow::anyhow!(\"Failed to parse response: {e}\"))?;\n\n            Ok(update_info)\n        })\n    })\n    .join()\n    .map_err(|_| anyhow::anyhow!(\"Update check thread panicked\"))?;\n\n    // Save to cache (convert to but_db types)\n    if let Ok(status) = &result {\n        let now = chrono::Utc::now();\n\n        // Get existing cache to preserve suppression\n        let existing = trans.update_check().get();","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-update/src/check.rs#L109-L145","documentation":"The update server answered, but error_for_status() converted the response into an error because the HTTP status was non-success (4xx/5xx). The message includes the status code and URL — e.g. 401/403 for auth token issues, 5xx for server-side problems.","triggerScenarios":"The X-Auth-Token header (build-time gitbutler_access_token secret) is rejected → 401/403; server maintenance or bug → 500; malformed channel/app_name in the request body → 400. Status appears in the {e} detail.","commonSituations":"Expired or missing build credentials; update service redeploying; requesting a channel that the endpoint no longer serves.","solutions":["Read the embedded status code in the error text to classify (4xx = request/auth problem, 5xx = server-side)","For 401/403, verify the build's gitbutler_access_token secret is present/valid","For 5xx, retry after a delay — server-side issues are usually transient","Check the requested channel (CHANNEL env at build time) is one the endpoint supports"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = check_status(...) {\n    let msg = e.to_string();\n    if msg.contains(\"Server returned error\") {\n        // 4xx: request/auth issue — report, don't retry; 5xx: back off and retry next session\n    }\n}","preventionTips":["Log the embedded status code to separate auth problems (401/403) from server issues (5xx)","Validate the built-in auth token in CI for release builds so 401s surface pre-release","Back off automatically after repeated 5xx instead of hammering the endpoint"],"tags":["rust","http","status-code","update-checker","but-update"],"backgroundTag":"http-error-response","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}