Summary
On the current dev branch, a dedicated server crashes with SIGSEGV every time any player joins the session. Repro rate is 100% (observed on every join attempt). Root cause is in ANotifications::FlavorTextRandomizer, which parses a config value (a file path string) as JSON content — the deserialize fails and the subsequent FlavorJson->TryGetStringArrayField(...) dereferences an invalid TSharedPtr, tripping Assertion failed: IsValid() [SharedPointer.h:1082].
Environment
- FRM:
dev @ a0b6056d ("Worked on my machine...") — installed from the green CI run's Linux Server Build / Client Build artifacts
- SML: 3.12.0 (release)
- Game: Satisfactory 1.2.2.2 CL#491125, dedicated server
- Server platform: Linux x64 (Ubuntu 22.04 container,
wolveix/satisfactory-server), mod installed at FactoryGame/Mods/GameFeatures/FicsitRemoteMonitoring/
- Client: Windows, same FRM commit + SML 3.12.0
Mod loads cleanly (GameFeature activates, all 92 HTTP endpoints register, /frm chat command registers). The crash is join-time only.
Expected vs actual
- Expected: player joins; the PlayerLogin webhook/notification path either sends a webhook (if configured) or no-ops.
- Actual:
Join succeeded is immediately followed by Assertion failed: IsValid() → SIGSEGV; the server dies and restarts. With no DiscIT.URL configured at all, the notification path still executes and crashes.
Stack trace (symbolized, from the server log)
Assertion failed: IsValid() [File:Runtime/Core/Public\Templates/SharedPointer.h] [Line: 1082]
Unhandled Exception: SIGSEGV: invalid attempt to write memory at address 0x0000000000000003
libFactoryServer-FicsitRemoteMonitoring-Linux-Shipping.so!ANotifications::FlavorTextRandomizer(EFlavorType) [SharedPointer.h:1082]
libFactoryServer-FicsitRemoteMonitoring-Linux-Shipping.so!ANotifications::SendWebhook(TMap<FString, FString, ...>, EFlavorType) [Notifications.cpp:61]
libFactoryServer-FicsitRemoteMonitoring-Linux-Shipping.so!ANotifications::execSendWebhook(UObject*, FFrame&, void*) [Notifications.gen.cpp:197]
libFactoryServer-CoreUObject-Linux-Shipping.so!UFunction::Invoke(...)
... (LatentActionManager -> UWorld::Tick -> UGameEngine::Tick)
Root cause (3 stacked issues in Source/FicsitRemoteMonitoring/Private/Libraries/Notifications.cpp)
FlavorTextRandomizer never loads the file. The config value (default: a file path) is fed directly to the JSON reader as if it were JSON content, and the result is used without an IsValid() guard:
FString WebhookJson = UFRMConfigManager::GetConfigOrDefault<FString>("DiscIT.FlavorJSON",
FPaths::ProjectDir() + "Mods/GameFeatrures/FicsitRemoteMonitoring/JSON/Flavor.json");
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(WebhookJson); // parses the PATH STRING
FJsonSerializer::Deserialize(Reader, FlavorJson); // fails -> FlavorJson invalid
FlavorJson->TryGetStringArrayField(TEXT("Any"), FlavorArray); // CRASH
Compare SendWebhook, which correctly calls URemoteMonitoringLibrary::FileLoadString(JsonPath, WebhookJson) first. FlavorTextRandomizer is missing that call.
-
Typo in every default path: Mods/GameFeatrures/ ("GameFeatrures" — extra r) in all 11 GetConfigOrDefault defaults in this file, so the defaults can never resolve even via the file-loading path.
-
Default filenames don't match shipped JSON: defaults reference Flavor.json and PlayerLogin.json, but the plugin ships FlavorText.json and PlayerOnline.json (JSON/ directory).
Also worth noting: SendWebhook runs unconditionally on the player-join event even when DiscIT.URL is empty — an early-out when no webhook URL is configured would avoid all of this work on servers that don't use webhooks.
Workaround (confirmed working)
Because the bug parses the config value as JSON content, supplying JSON content as the value avoids the crash. In Server Manager → Server Settings → Ficsit Remote Monitoring → Flavor Text Array JSON Path, set:
{"Any":["[FRM]"],"Player":["{Player} changed online status"],"Positive":[":)"],"Detrimental":[":("],"Power":["power event"],"Battery":["battery level"],"Train":["train event"],"Doggo":["doggo found something"],"Research":["research done"]}
(All category keys populated, since the post-parse random pick from an empty array would be the next failure.) After Apply + server restart, players join normally — verified.
Suggested resolution
In FlavorTextRandomizer:
- call
URemoteMonitoringLibrary::FileLoadString(JsonPath, WebhookJson) (matching SendWebhook) before creating the JSON reader, and
- guard the deserialize result (
if (!FlavorJson.IsValid()) { log + return fallback; }) so a missing/corrupt file can never crash the server,
- fix the
GameFeatrures → GameFeatures typo in all defaults,
- align default filenames with the shipped JSON (
FlavorText.json, PlayerOnline.json).
Happy to open a PR with the above if useful (compile-untested locally — no UE toolchain here — but mechanical, and your CI builds PRs).
Minor related observation
In the Server Manager settings UI on the same build, the last three FRM fields appear label-shifted ("Train Error JSON Path" / "Train Idle JSON Path" both show the value 180, which presumably belongs to "Train Idle Delay") — possibly an ordering issue in the new config registration.
Diagnosis assisted by Claude Code; logs and repro from a live dedicated server.
Summary
On the current
devbranch, a dedicated server crashes with SIGSEGV every time any player joins the session. Repro rate is 100% (observed on every join attempt). Root cause is inANotifications::FlavorTextRandomizer, which parses a config value (a file path string) as JSON content — the deserialize fails and the subsequentFlavorJson->TryGetStringArrayField(...)dereferences an invalidTSharedPtr, trippingAssertion failed: IsValid() [SharedPointer.h:1082].Environment
dev@a0b6056d("Worked on my machine...") — installed from the green CI run's Linux Server Build / Client Build artifactswolveix/satisfactory-server), mod installed atFactoryGame/Mods/GameFeatures/FicsitRemoteMonitoring/Mod loads cleanly (GameFeature activates, all 92 HTTP endpoints register,
/frmchat command registers). The crash is join-time only.Expected vs actual
Join succeededis immediately followed byAssertion failed: IsValid()→ SIGSEGV; the server dies and restarts. With noDiscIT.URLconfigured at all, the notification path still executes and crashes.Stack trace (symbolized, from the server log)
Root cause (3 stacked issues in
Source/FicsitRemoteMonitoring/Private/Libraries/Notifications.cpp)FlavorTextRandomizernever loads the file. The config value (default: a file path) is fed directly to the JSON reader as if it were JSON content, and the result is used without anIsValid()guard:Compare
SendWebhook, which correctly callsURemoteMonitoringLibrary::FileLoadString(JsonPath, WebhookJson)first.FlavorTextRandomizeris missing that call.Typo in every default path:
Mods/GameFeatrures/("GameFeatrures" — extrar) in all 11GetConfigOrDefaultdefaults in this file, so the defaults can never resolve even via the file-loading path.Default filenames don't match shipped JSON: defaults reference
Flavor.jsonandPlayerLogin.json, but the plugin shipsFlavorText.jsonandPlayerOnline.json(JSON/directory).Also worth noting:
SendWebhookruns unconditionally on the player-join event even whenDiscIT.URLis empty — an early-out when no webhook URL is configured would avoid all of this work on servers that don't use webhooks.Workaround (confirmed working)
Because the bug parses the config value as JSON content, supplying JSON content as the value avoids the crash. In Server Manager → Server Settings → Ficsit Remote Monitoring → Flavor Text Array JSON Path, set:
{"Any":["[FRM]"],"Player":["{Player} changed online status"],"Positive":[":)"],"Detrimental":[":("],"Power":["power event"],"Battery":["battery level"],"Train":["train event"],"Doggo":["doggo found something"],"Research":["research done"]}(All category keys populated, since the post-parse random pick from an empty array would be the next failure.) After Apply + server restart, players join normally — verified.
Suggested resolution
In
FlavorTextRandomizer:URemoteMonitoringLibrary::FileLoadString(JsonPath, WebhookJson)(matchingSendWebhook) before creating the JSON reader, andif (!FlavorJson.IsValid()) { log + return fallback; }) so a missing/corrupt file can never crash the server,GameFeatrures→GameFeaturestypo in all defaults,FlavorText.json,PlayerOnline.json).Happy to open a PR with the above if useful (compile-untested locally — no UE toolchain here — but mechanical, and your CI builds PRs).
Minor related observation
In the Server Manager settings UI on the same build, the last three FRM fields appear label-shifted ("Train Error JSON Path" / "Train Idle JSON Path" both show the value
180, which presumably belongs to "Train Idle Delay") — possibly an ordering issue in the new config registration.Diagnosis assisted by Claude Code; logs and repro from a live dedicated server.