Skip to content

ModsDownloadingPatch throws when workshop query fails and __result.Mods is null #632

@SWQXDBA

Description

@SWQXDBA

When world mod download or workshop query fails during server startup, Torch.Patches.ModsDownloadingPatch.Postfix(...) can throw its own exception instead of only logging diagnostic information.

The visible error is:

Keen: Exception while loading world: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.All[TSource](IEnumerable`1 source, Func`2 predicate)
   at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
   at Torch.Patches.ModsDownloadingPatch.Postfix(ResultData __result, List`1 mods) in C:\ProgramData\Jenkins\.jenkins\workspace\Torch_master\Torch\Patches\ModsDownloadingPatch.cs:line 40
   at Patched_Sandbox.Engine.Networking.MyWorkshopDownloadWorldModsBlocking_0(List`1 cancelToken, CancelToken)
   at Patched_Sandbox.MySandboxGameInitQuickLaunch_0(Object)

The current implementation is:

public static void Postfix(MyWorkshop.ResultData __result, List<MyObjectBuilder_Checkpoint.ModItem> mods)
{
    if (__result.Result == MyGameServiceCallResult.OK) return;
    _log.Warn("Missing Mods:");
    var mismatchMods = mods.Where(b => __result.Mods.All(c => b.PublishedFileId != c.Id));
    foreach (var mod in mismatchMods)
        _log.Warn($"\t{mod.PublishedFileId} : {mod.FriendlyName}");
}

From the observed failure path, __result.Mods can be null when the workshop query itself fails. In that case, this line throws:

__result.Mods.All(...)

because LINQ receives a null source.

So there are effectively two layers here:

  1. The upstream workshop query or download failed.
  2. ModsDownloadingPatch then throws a secondary exception while trying to report missing mods.

This patch appears to be intended for diagnostic logging, but in its current form it can turn a workshop failure into an additional exception inside Torch itself.

A safer behavior would be for ModsDownloadingPatch to handle these cases defensively:

  • mods == null
  • __result.Mods == null
  • __result.Mods.Count == 0

and only log what is available, without throwing from the postfix itself.

Suggested changes:

  1. Guard both mods and __result.Mods before running any LINQ over them.
  2. Treat a null or empty __result.Mods collection as a failed or incomplete workshop lookup and log that condition explicitly.
  3. Keep the postfix best-effort only: it should never replace the original workshop failure with a secondary Torch exception.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions