dotnet/reactive · error · InvalidOperationException

RxMainPackage must not be null.

Error message

RxMainPackage must not be null.

What it means

Validate() expects RxMainPackage to be a non-null string; Spectre.Console never supplies null for these options, so null indicates RxSourceSettings is being used outside the supported Spectre.Console path. The method throws InvalidOperationException instead of returning a validation error in that case. It is an API-misuse guard, not a user-input error.

Solutions

  1. Set RxMainPackage to a non-null string in '<PackageId>,<Version>' format before calling Validate()
  2. Instantiate and populate RxSourceSettings through the Spectre.Console command pipeline instead of manually
  3. If you must construct it manually, initialize all required properties: RxMainPackage and RxUiFrameworkPackages

Example fix

// before
var settings = new RxSourceSettings { RxUiFrameworkPackages = new[] { "Rx.WPF,1.0.0" } };
var result = settings.Validate();
// after
var settings = new RxSourceSettings { RxMainPackage = "System.Reactive,6.0.1", RxUiFrameworkPackages = new[] { "Rx.WPF,1.0.0" } };
var result = settings.Validate();
Defensive patterns

Strategy: validation

Validate before calling

if (settings.RxMainPackage is null) { throw new ArgumentException("RxMainPackage must be set before Validate()", nameof(settings)); }

Type guard

bool usable = settings.RxMainPackage is string s && !string.IsNullOrWhiteSpace(s);

Try / catch

try { settings.Validate(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("RxMainPackage must not be null")) { /* construct via Spectre.Console instead */ }

Prevention

When it happens

Trigger: Calling Validate() (directly or via RxPackagesParsed/GetParsedPackage) on an RxSourceSettings instance constructed manually with RxMainPackage left null, i.e. not bound by Spectre.Console's CommandSettings binder.

Common situations: Unit tests or scripts instantiating RxSourceSettings with object initializers and forgetting RxMainPackage; custom tooling bypassing the Spectre.Console command layer.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/be04224d286f4826. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Test/Gauntlet/RxGauntlet.Common/CommandLine/RxSourceSettings.cs:100

            ..RxUiFrameworkPackagesParsed
        ];

    /// <summary>
    /// Validates the command line argument(s).
    /// </summary>
    /// <returns>A value indicating whether the settings are valid.</returns>
    /// <exception cref="InvalidOperationException">
    /// Thrown if this object's properties are set in a way that we do not expect from Spectre Console CLI.
    /// </exception>
    public override ValidationResult Validate()
    {
        // Spectre Console will never make the following properties null, so this can only mean that we're being used
        // in an unsupported way (probably not via Spectre.Console) so we throw instead of reporting a validation
        // failure.

        if (RxMainPackage is not string rxMainPackage)
        {
            throw new InvalidOperationException($"{nameof(RxMainPackage)} must not be null.");
        }

        if (RxUiFrameworkPackages is not string[] rxUiPackages)
        {
            throw new InvalidOperationException($"{nameof(RxUiFrameworkPackages)}  must not be null.");
        }

        if (!PackageIdAndVersion.TryParse(rxMainPackage, out _parsedRxMainPackage))
        {
            return ValidationResult.Error($"Invalid package specification: {RxMainPackage}. Must be <PackageId>,<Version>");
        }

        if (RxLegacyPackage is string rxLegacyPackage &&
            !PackageIdAndVersion.TryParse(rxLegacyPackage, out _parsedRxLegacyPackage))
        {
            return ValidationResult.Error($"Invalid package specification: {rxLegacyPackage}. Must be <PackageId>,<Version>");
        }

View on GitHub (pinned to 94b5d5ab91)