[updater] downloadAndInstall() intermittently fails on some Windows devices with error sending request for url (…/release.json)
Summary
On a subset of Windows machines (Windows 10/11; exact mix unknown), calling downloadAndInstall() fails with:
error sending request for url (https://releases.myapp.com/latest/release.json)
It’s not reproducible on my dev machine, but I’m seeing Sentry reports from production users. The failure is recorded at the downloadAndInstall stage, even though the error references the metadata URL (release.json).
Triggers / invocation context
I call checkForAppUpdates() in two places:
- automatically on app launch, and
- manually when the user clicks the version label. (Both cases crashes with the same error)
The error has been observed in production in both invocation paths, but only on a subset of Windows machines. It is not deterministic and is not reproducible on my dev machine.
Code & Config
Rust:
fn main() {
tauri::Builder::default()
.setup(|app| {
#[cfg(desktop)]
app.handle().plugin(tauri_plugin_updater::Builder::new().build())?;
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
JS:
import { check } from '@tauri-apps/plugin-updater'
import { ask, message } from '@tauri-apps/plugin-dialog'
import { exit, relaunch } from '@tauri-apps/plugin-process'
import * as Sentry from '@sentry/vue'
class DownloadAndInstallError extends Error {
constructor(message: string) {
super(message)
this.name = 'DownloadAndInstallError'
}
}
class CheckForUpdateError extends Error {
constructor(message: string) {
super(message)
this.name = 'CheckForUpdateError'
}
}
export const checkForAppUpdates = async () => {
try {
const update = await check().catch((error: unknown) => {
throw new CheckForUpdateError(
`Failed to check for updates: ${String(error)}`,
)
})
if (update) {
const yes = await ask(`Update to ${update.version} is available!\n\n`, {
title: 'Update Available',
kind: 'info',
okLabel: 'Update',
cancelLabel: 'Cancel',
})
if (yes) {
await update.downloadAndInstall().catch((error) => {
throw new DownloadAndInstallError(error.message)
})
await relaunch()
}
}
} catch (error) {
const stage =
error instanceof DownloadAndInstallError
? 'downloadAndInstall'
: error instanceof CheckForUpdateError
? 'check'
: 'unknown'
Sentry.captureException(error, {
tags: { area: 'updater', stage },
})
}
}
tauri.conf.json:
"plugins": {
"updater": {
"pubkey": "signing-pub-key",
"endpoints": ["https://releases.myapp.com/latest/release.json"],
"windows": {
"installMode": "passive"
}
}
}
Versions
JS: @tauri-apps/plugin-updater@~2.9.0
Rust: tauri-plugin-updater = "=2.9.0"
Expected behavior
check()returns an update.downloadAndInstall()downloads and installs without re-fetch failures.
Actual behavior
- On some Windows devices,
downloadAndInstall()errors out with error sending request for url (…/release.json). - It looks like the request may not be sent or fails very early (no status code in the error, just a generic send error).
Environment details from telemetry (examples)
- OS: Windows ≥ 10 (mix of 10/11 unspecified)
- WebView2/Edge runtime (example from one event): 139.0.0
Questions
- Does
downloadAndInstall()re-validate or re-fetch release.json internally even when the update object comes fromcheck()? - Are there known differences in HTTP client behavior between
check()anddownloadAndInstall()(e.g., proxy usage, TLS options, timeouts) that could explain a “send” failure only at the install stage? - Any recommended logging or RUST_LOG categories to capture deeper reqwest/TLS/proxy diagnostics we can ship to affected users?
Does downloadAndInstall() re-validate or re-fetch release.json internally even when the update object comes from check()?
No.
Are there known differences in HTTP client behavior between check() and downloadAndInstall() (e.g., proxy usage, TLS options, timeouts) that could explain a “send” failure only at the install stage?
No, they use the same defaults / configs.
Any recommended logging or RUST_LOG categories to capture deeper reqwest/TLS/proxy diagnostics we can ship to affected users?
Hmm, reqwest logs quite a bit on the debug and trace levels though it's rarely actually helpful from what i've seen. Still worth a try. I'd say the easiest is to use tauri's log plugin, set it to debug or trace and ask users to give you the log file if you know them.