Repository navigation
Make BepInEx/ValheimPlus updaters resilient to transient API failures (fixes #778) - #781
Merged
JustinTArthur merged 3 commits intoOct 4, 2026
Conversation
Fixes community-valheim-tools#778 Thunderstore.io (BepInEx) and GitHub (ValheimPlus) APIs intermittently return 403/5xx (Cloudflare bot management, rate limits, brief outages). The previous code did a single curl with no retry and no fallback, so a transient blip would: 1. fail bepinex-updater / valheim-plus-updater with `fatal` 2. cause check_mod in valheim-updater to return non-zero 3. cause update() to bail out before write_restart_file 4. leave valheim-server unstarted until the next UPDATE_CRON tick Three changes: * Add curl --retry 5 --retry-delay 5 --retry-all-errors --retry-max-time 90 to both updaters, plus a stable User-Agent ("valheim-server-docker") so CDNs don't lump us in with default-curl traffic. * Fall back to the existing mod installation in check_mod when the updater fails but $mod_install_path/valheim_server.x86_64 is already present from a previous successful merge. Mirrors the existing Steam download fallback in update() (valheim-updater:51-58). This is the fix that actually unsticks cold starts after a transient API blip. * Leave the "mod disabled but previously installed" refresh path unchanged - it's opportunistic and not load-bearing for boot.
dreeko
force-pushed
the
fix/issue-778-mod-updater-resilience
branch
from
May 14, 2026 03:03
4f705bc to
11ee8ed
Compare
dreeko
marked this pull request as ready for review
May 14, 2026 03:04
JoeTuohy
approved these changes
Sep 20, 2026
Both updaters' API calls and download_mod now go through fetch_url, which retries the transient refusals from Thunderstore's and GitHub's CDNs (community-valheim-tools#778) and caps each attempt with --connect-timeout/--max-time so one stalled transfer can't hang the updater. API calls use a 30s cap. download_mod needed this as well, since the archive download from thunderstore.io sits behind the same Cloudflare as its API. It now downloads to a temp file and only replaces the cached archive once complete, so a failed download no longer leaves a partial archive for check_merge to extract when a Valheim update requests a merge.
JustinTArthur
approved these changes
Oct 4, 2026
JustinTArthur
left a comment
Collaborator
There was a problem hiding this comment.
Thanks for the contribution. I'm moving it to a common function to cut down on repetition, then will merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #778. Issue reporter saw a transient
HTTP 403from Thunderstore's API on container restart, which permanently blocked the Valheim server from starting (workaround was disablingBEPINEX).Thunderstore.io (BepInEx) and the GitHub releases API (ValheimPlus) both sit behind CDNs/WAFs that intermittently 403/429/5xx automated clients, especially on default
curlUser-Agent. The previous code did a single one-shotcurlwith no retry and no fallback, so any blip cascaded into a startup outage:bepinex-updater(orvalheim-plus-updater) callsfataland exits 1.check_modinvalheim-updaterreturns non-zero.update()bails out beforewrite_restart_file.check_server_restartnever sees a restart marker, sosupervisorctl start valheim-serveris never called.UPDATE_CRONtick succeeds.This is asymmetric with the existing Steam-download path in
update()(valheim-updater:51-58), which already falls back to a locally-cachedvalheim_server.x86_64when Steam fails.Changes
bepinex-updater/valheim-plus-updater: Addcurl --retry 5 --retry-delay 5 --retry-all-errors --retry-max-time 90and a stableUser-Agent: valheim-server-dockerto both API calls.--retry-all-errorsrequires curl >= 7.71 (trixie ships 8.x, so fine).valheim-updater(check_mod): When the mod updater fails and$mod_install_path/valheim_server.x86_64already exists from a previous successful merge, log a warning and return 0 instead of blocking the boot. The nextUPDATE_CRONtick still gets a chance to apply updates.The "mod disabled but previously installed" refresh branch in
check_modis intentionally left alone — it's an opportunistic refresh and isn't load-bearing for server startup.