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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions