Skip to content

Handle WorldOption.sav blocking settings on Windows->Linux migration (fixes #886) - #910

Open
NathanFant wants to merge 2 commits into
thijsvanloef:mainfrom
NathanFant:fix/worldoption-sav-migration-blocks-settings
Open

Handle WorldOption.sav blocking settings on Windows->Linux migration (fixes #886)#910
NathanFant wants to merge 2 commits into
thijsvanloef:mainfrom
NathanFant:fix/worldoption-sav-migration-blocks-settings

Conversation

@NathanFant

Copy link
Copy Markdown

Context

Fixes #886.

A WorldOption.sav carried over from a save that was ever played on Windows (including via Steam's "host from save data" co-op mode) takes priority over PalWorldSettings.ini and silently prevents the new server's settings -- including AdminPassword -- from applying. This causes RCON and the REST API to reject a correctly-configured admin password with "AdminPassword is empty" / Authentication failed!, even when that password is verified correct in the container environment and in the generated PalWorldSettings.ini.

#886's original report identified the root cause and confirmed deleting WorldOption.sav fixes it, but no code change landed -- the existing migration/ docs and script don't mention this at all, so anyone following the officially documented migration path still hits it.

Changes

  • migration/migrate.sh: after copying the save into place, moves aside (does not delete) any pre-existing WorldOption.sav in the migrated save directory, so scripted migrations are unaffected by default.
  • migration/README.md: documents the same step for manual migrations (new step 4), plus a callout at the top of the script instructions explaining why this matters and linking to [LOG] REST accessed endpoint / Unauthorized (AdminPassword is empty) #886.

Chose "move aside" (WorldOption.sav -> WorldOption.sav.bak) rather than deleting outright, so the original file is still recoverable if anyone needs it for reasons unrelated to this bug.

Verification

Reproduced and fixed against a real production migration (Windows-hosted save -> Linux dedicated server, via this same image):

  1. Confirmed AdminPassword was correct in the container env and in the freshly-generated PalWorldSettings.ini (byte-for-byte, matching quoting) -- RCON and REST API (/v1/api/info) both still rejected it.
  2. Ruled out a config-regeneration race by setting DISABLE_GENERATE_SETTINGS=true and restarting against an untouched, already-correct ini -- symptom persisted identically.
  3. Ruled out client-side request formatting by manually constructing the Base64 Authorization: Basic header and comparing byte-for-byte against curl -u's automatic handling -- identical, and the server's own 401 response confirmed the failure is server-side (WWW-Authenticate: Basic realm="Pal", body Unauthorized (AdminPassword is empty)).
  4. Moved WorldOption.sav aside (this PR's fix) and restarted -- RCON and REST API immediately worked. Confirmed via the server's own logs: RCON executed the command. Save, RCON executed the command. ShowPlayers. REST API's /v1/api/info and /v1/api/players returned real, correctly-authenticated responses. All custom settings (drop-item caps, building limits, invader-enemy toggle, etc.) remained correctly applied from PalWorldSettings.ini -- this fix does not reset or lose any other configuration.

Checklist before requesting a review

  • I have performed a self-review/test of my code
  • I've not introduced breaking changes (the moved-aside file is inert; nothing reads WorldOption.sav.bak)
  • My changes do not violate linting rules

A WorldOption.sav carried over from a save that was ever played on
Windows takes priority over PalWorldSettings.ini and silently prevents
the new server's settings -- including AdminPassword -- from applying.
This causes RCON/REST API authentication to fail with "AdminPassword is
empty" even when the password is correctly configured everywhere else
(container env, generated PalWorldSettings.ini, etc.), as reported in thijsvanloef#886.

- migrate.sh now moves aside (not deletes) any pre-existing
  WorldOption.sav in the migrated save automatically.
- README.md documents the same step for manual migrations, and adds a
  callout explaining why this matters before the script instructions.

Verified against a real, production migration: same symptom (RCON and
REST API both rejecting a verified-correct AdminPassword with "empty"
errors) reproduced on two different hosts, persisted across container
restarts and even with config regeneration disabled entirely (ruling out
a regeneration race), and was resolved immediately by moving
WorldOption.sav aside -- confirmed via the server's own logs showing
RCON commands actually executing afterward.

Closes thijsvanloef#886
NathanFant added a commit to NathanFant/palworld-infrastructure that referenced this pull request Jul 28, 2026
…heck

Previous commit accidentally moved palworld-ctl start into the
Windows-migration-only conditional block, meaning a save that was never
played on Windows would never get a start instruction at all. The start
command now always runs regardless of whether the WorldOption.sav step
applied. Also softened "upstream fix" to "fix proposed upstream" since
thijsvanloef/palworld-server-docker#910 isn't merged yet.

Addresses review feedback on PR #114.
NathanFant added a commit to NathanFant/palworld-infrastructure that referenced this pull request Jul 28, 2026
* Document WorldOption.sav gotcha in migration runbooks

Root cause of #105 (RCON/REST API "AdminPassword is empty"): a
WorldOption.sav carried over from a save ever played on Windows takes
priority over PalWorldSettings.ini and silently blocks new server
settings -- including AdminPassword -- from applying. Confirmed via
thijsvanloef/palworld-server-docker#886 and fixed upstream via this
project's own PR, thijsvanloef/palworld-server-docker#910.

Both runbooks now note to move aside (not delete) any WorldOption.sav
from a Windows-originated save before starting the server.

Closes #113

* Fix: restore unconditional palworld-ctl start after WorldOption.sav check

Previous commit accidentally moved palworld-ctl start into the
Windows-migration-only conditional block, meaning a save that was never
played on Windows would never get a start instruction at all. The start
command now always runs regardless of whether the WorldOption.sav step
applied. Also softened "upstream fix" to "fix proposed upstream" since
thijsvanloef/palworld-server-docker#910 isn't merged yet.

Addresses review feedback on PR #114.
@thijsvanloef
thijsvanloef requested a lite review from Copilot August 20, 2026 19:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a Windows→Linux migration pitfall where an existing WorldOption.sav can silently override PalWorldSettings.ini, preventing server settings (notably AdminPassword) from applying and causing RCON/REST authentication failures (fixes #886).

Changes:

  • Update migration/migrate.sh to move WorldOption.sav aside after copying a migrated save.
  • Update migration/README.md to document the issue and add a manual migration step to move WorldOption.sav aside.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
migration/README.md Adds an IMPORTANT migration warning and a manual step to move WorldOption.sav aside to avoid settings being overridden.
migration/migrate.sh Automatically backs up WorldOption.sav (moves it to .bak) during scripted migrations to prevent settings override.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread migration/README.md Outdated
Comment thread migration/migrate.sh
Comment on lines +28 to +32
WORLD_OPTION_SAV="./palworld/Pal/Saved/SaveGames/0/${MIGRATION_SERVER_NAME}/WorldOption.sav"
if [ -f "${WORLD_OPTION_SAV}" ]; then
echo "########## MOVING ASIDE WorldOption.sav (see #886) ##########"
mv "${WORLD_OPTION_SAV}" "${WORLD_OPTION_SAV}.bak"
fi
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@NathanFant

Copy link
Copy Markdown
Author

Looks like copilot hung up on linting. I fixed this locally and use it currently. Leaving review and fixing up to y'all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[LOG] REST accessed endpoint / Unauthorized (AdminPassword is empty)

2 participants