Satisfactory Field guide

Cannot join Satisfactory after an update: fix a version mismatch

Compare Satisfactory client and running-server builds, identify the right installation and update while retaining a rollback path.

Cannot join Satisfactory after an update: fix a version mismatch

A successful download does not prove that players are connecting to the files you updated. Before repeating SteamCMD, compare the client's branch and game build with the running server's startup log, then confirm the service starts the same installation that the updater changes.

This procedure targets an unmodded PC dedicated server on native Linux. It follows our Ubuntu setup: satisfactory.service, account satisfactory, standalone updater /home/satisfactory/steamcmd/steamcmd.sh, installation /home/satisfactory/server and HOME /home/satisfactory. Adjust those paths only after inspecting your unit. Container images and Windows services have different update mechanisms. A PC dedicated-server update does not add console support.

Record both sides of the mismatch#

Capture the exact error and the client game's displayed version/build. In Steam, inspect the selected branch under Properties → Betas. The normal public branch and Experimental are different selections; Coffee Stain describes Experimental and launcher selection. With Epic, confirm which game entry you launched. Restart the launcher if its update status appears stale.

Then inspect the server:

bash
sudo systemctl show satisfactory.service \
  -p ActiveState -p MainPID -p User -p WorkingDirectory -p ExecStart
sudo systemctl cat satisfactory.service
sudo journalctl -u satisfactory.service -n 160 --no-pager -o short-iso
sudo head -n 120 /home/satisfactory/server/FactoryGame/Saved/Logs/FactoryGame.log

Use startup lines from the current invocation. An old log or a file left by another installation can mislead. Record the game's reported build/compatibility information and the branch used by your updater. SteamPipe build IDs and game-reported changelist/version identifiers are different kinds of identifier; do not require unrelated numbers to match just because both say “build.”

ObservationNext check
One client fails; other current clients joinThat client's launcher, branch and installed files
Every client reports a server version mismatchActual server build, update target and selected branch
No response or connection timeoutNetworking and endpoint checks
Server accepts connections but rejects one saveSave compatibility and game log, separately from client compatibility

A reported mismatch after running the updater illustrates the diagnostic trap. A forum answer cannot establish which build your process is executing.

Prove the updater targets the live installation#

Compare WorkingDirectory and the absolute ExecStart path against +force_install_dir. A command run from another SSH user's home can update a second copy successfully while systemd keeps launching the old one. Always use the explicit installation directory and the unprivileged game account.

Check ExecStartPre, scheduled jobs, panel update settings and container policies for another updater. A pre-start command selecting Experimental can undo a manual public-branch update on the next start. Make branch choice consistent in the system that owns updates. Do not apply native-host commands inside an unrelated container or let two updaters operate on the same directory.

Before touching files, make a named manual save and wait for completion. Record the session, checkpoint and current build. Preserve persistent saves, blueprints, settings and deployment details using the backup guide; for rollback, also retain a recoverable old installation and its compatible pre-change state. An archive of world files alone does not reproduce the old executable.

Stop cleanly and select the branch deliberately#

Inspect the unit first: the example uses KillSignal=SIGINT. Schedule maintenance, pause any owned update job, then stop the service:

bash
sudo systemctl stop satisfactory.service
sudo systemctl show satisfactory.service \
  -p ActiveState -p SubState -p MainPID -p Result
sudo journalctl -u satisfactory.service -n 80 --no-pager

Continue only after a clean stop with no remaining game process or independent writer. Investigate a timeout or failed stop. Do not force-kill it and immediately overwrite its files. The following guarded example selects the public branch; it is appropriate only when that is the agreed client branch and the preserved save is compatible:

bash
(
  set -e
  test "$(sudo systemctl show satisfactory.service -p ActiveState --value)" = inactive
  test "$(sudo systemctl show satisfactory.service -p MainPID --value)" = 0
  test "$(sudo systemctl show satisfactory.service -p Result --value)" = success
  sudo -u satisfactory -H /home/satisfactory/steamcmd/steamcmd.sh \
    +force_install_dir /home/satisfactory/server \
    +login anonymous +app_update 1690800 -beta public validate +quit
)

The dedicated-server service reference shows explicit branch selection; Valve documents SteamCMD. For a deliberately Experimental group, change only -beta public to -beta experimental, after preserving the state and agreeing that branch with players. Do not run both variants in sequence. Explicit public selection also avoids depending on a previous branch choice: a historical report describes that exact source of confusion.

Read the updater's output and confirm a successful completion for app 1690800; a successful shell return alone is insufficient. If the download, authentication or validation fails, leave the service stopped, retain the output and correct that problem first. Validation can replace modified installation files, so preserve customisations beforehand. It does not validate world compatibility or restore a backup.

Align branch and compatible game builds, then test a real join. Save compatibility remains a separate gate.

Restart the intended instance and check a new log#

Only after the updater succeeds, start deliberately:

bash
sudo systemctl start satisfactory.service
sudo journalctl -u satisfactory.service --since '-5 minutes' \
  --no-pager -o short-iso

Confirm these are new startup records, the expected install path is running and no pre-start updater selected another branch. Reconnect to the original host and port with the agreed updated client. Verify the factory's recorded checkpoint, save again, gracefully restart and rejoin. That checks persistent state alongside connection compatibility.

If a mismatch remains, compare the newly reported builds again. Check saved Server Manager entries, DNS and port forwarding for another instance. Do not reset server identity or delete ServerSettings to solve a version problem. If the correct branch has not delivered a compatible server/client pair, retain the stopped-state backup and check the publisher's release notes; repeated reinstallations cannot publish a missing build.

Switching back to public is not a save-file downgrade tool. Never open your only newer-branch world in older binaries to “try it.” Rehearse on a separate compatible instance and preserve the original bytes. If rollback is necessary, restore the matched older installation and its pre-change persistent state, keeping the newer state separately for recovery. Report a reproducible unresolved mismatch with redacted build, branch, endpoint and updater evidence rather than a password-bearing full log.