stride3d/stride · error · Exception

Could not parse a valid version from

Error message

Could not parse a valid version from {sourceFile} (MajorMinor='{majorMinor}', Patch='{patch}'). Check the 'MajorMinor = "x.y";' and 'Patch = "n";' lines.

What it means

StrideVersionTasks.ReadInputs parses version fields (MajorMinor, Patch, NuGetVersionSuffix) out of a source file via regex and validates them before building the composed version string. If MajorMinor does not match 'x.y' or Patch is not a number, it throws with the parsed values and the file path, so a malformed version is never silently propagated into packages or compiled constants.

Solutions

  1. Open the file named in the message and fix the MajorMinor/Patch lines to the exact shapes MajorMinor = "4.2"; and Patch = "1";.
  2. Restore the version file from git (git checkout -- <file>) if the lines were accidentally changed or deleted.
  3. Re-run whatever tool injects version properties into the file before invoking ReadInputs.
  4. Check for merge-conflict markers or commented-out lines inside the version file.

Example fix

// before (StrideVersion.props)
<PropertyGroup><MajorMinor>4</MajorMinor><Patch></Patch></PropertyGroup>
// after
// MajorMinor = "4.2";
// Patch = "1";
Defensive patterns

Strategy: validation

Validate before calling

static void ValidateVersionFile(string path)
{
    var data = File.ReadAllText(path);
    var mm = Regex.Match(data, "MajorMinor = \"([^\"]*)\";").Groups[1].Value;
    var patch = Regex.Match(data, "Patch = \"([^\"]*)\";").Groups[1].Value;
    if (!Regex.IsMatch(mm, @"^[0-9]+\.[0-9]+$") || !Regex.IsMatch(patch, @"^[0-9]+$"))
        throw new InvalidOperationException($"{path} has invalid MajorMinor='{mm}' or Patch='{patch}'.");
}

Type guard

static bool IsWellFormedVersion(string majorMinor, string patch) =>
    Regex.IsMatch(majorMinor ?? "", @"^[0-9]+\.[0-9]+$") &&
    Regex.IsMatch(patch ?? "", @"^[0-9]+$");

Try / catch

try
{
    versionTasks.ReadInputs();
}
catch (Exception ex) when (ex.Message.Contains("Could not parse a valid version from"))
{
    logger.Error($"Version source file malformed: {ex.Message}. Restore MajorMinor/Patch lines.");
    throw;
}

Prevention

When it happens

Trigger: Calling ReadInputs when the version source file's 'MajorMinor = "x.y";' or 'Patch = "n";' lines are missing, renamed, commented out, reformatted (e.g. extra spaces, single quotes), or contain placeholders/empty strings — Field() then returns "" and the regex checks fail.

Common situations: Manual edits to the version file during release prep; branch merges dropping the version block; CI checking out a file where version props are injected by another tool that didn't run; accidental change of assignment style ("=" spacing or semicolon removed).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/b1385ff90a7d143d. Report an issue: GitHub.

Appendix: source

Thrown at sources/targets/StrideVersionTasks.cs:35

using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

// Shared version logic for both the dev and release generators.
internal static class StrideVersionUtil
{
    // Reads the editable inputs from SharedAssemblyInfo.cs. The version is composed MajorMinor.Patch (Patch is the
    // only patch source; MajorMinor the only major.minor source — no duplication to drift).
    public static void ReadInputs(string sourceFile, out string majorMinor, out string version, out string suffix)
    {
        string data = File.ReadAllText(sourceFile);
        majorMinor = Field(data, "MajorMinor");
        string patch = Field(data, "Patch");
        suffix = Field(data, "NuGetVersionSuffix");
        // Fail loudly on an unparseable version rather than emit a malformed one (e.g. "." or "4.4.") that would
        // ship a weird package or compile a garbage const. Field returns "" when a line's shape changed.
        if (!Regex.IsMatch(majorMinor, @"^[0-9]+\.[0-9]+$") || !Regex.IsMatch(patch, @"^[0-9]+$"))
            throw new Exception("Could not parse a valid version from " + sourceFile + " (MajorMinor='" + majorMinor +
                "', Patch='" + patch + "'). Check the 'MajorMinor = \"x.y\";' and 'Patch = \"n\";' lines.");
        version = majorMinor + "." + patch;
    }

    private static string Field(string data, string name)
        => Regex.Match(data, name + " = \"([^\"]*)\";").Groups[1].Value;

    public static string Git(string workingDir, string args)
    {
        var psi = new ProcessStartInfo("git", args)
        {
            WorkingDirectory = workingDir,
            RedirectStandardOutput = true,
            UseShellExecute = false
        };
        using (var p = Process.Start(psi))
        {
            string output = p.StandardOutput.ReadToEnd().Trim();

View on GitHub (pinned to 96fad776d2)