SubtitleEdit/subtitleedit · error · ArgumentException
Invalid version format
Error message
Invalid version format
What it means
ArgumentException from the SemanticVersion constructor when input fails the regex ^(\d+)\.(\d+)\.(\d+)(?:-([a-z]+)(\d+)?)?$ (IgnoreCase). It requires exactly three numeric components and an optional single-word prerelease tag optionally followed by digits; a leading 'v' is tolerated.
Source
Thrown at src/ui/Logic/SematicVersion.cs:24
public class SemanticVersion
{
public int Major { get; set; }
public int Minor { get; set; }
public int Patch { get; set; }
public string PreRelease { get; set; }
public int PreReleaseNumber { get; set; }
public int PreReleaseRank { get; set; }
public SemanticVersion(string input)
{
var trimmedInput = input.Trim();
PreRelease = string.Empty;
var version = trimmedInput.StartsWith("v") ? trimmedInput.Substring(1) : trimmedInput;
var match = Regex.Match(version, @"^(\d+)\.(\d+)\.(\d+)(?:-([a-z]+)(\d+)?)?$", RegexOptions.IgnoreCase);
if (!match.Success)
{
throw new ArgumentException("Invalid version format", nameof(trimmedInput));
}
Major = int.Parse(match.Groups[1].Value);
Minor = int.Parse(match.Groups[2].Value);
Patch = int.Parse(match.Groups[3].Value);
if (match.Groups[4].Success)
{
PreRelease = match.Groups[4].Value.ToLowerInvariant();
PreReleaseRank = GetPreReleaseRank(PreRelease);
PreReleaseNumber = match.Groups[5].Success ? int.Parse(match.Groups[5].Value) : 0;
}
else
{
PreRelease = string.Empty;
PreReleaseRank = int.MaxValue; // final/stable is considered highest
}
}View on GitHub (pinned to 17a9f07487)
Solutions
- Normalize input to MAJOR.MINOR.PATCH[-wordNNN] before constructing SemanticVersion (strip build metadata after '+').
- Validate with the same regex before calling the constructor and surface a clear error to the user.
- If richer SemVer (dotted prerelease, build metadata) is genuinely needed, extend the regex or adopt a dedicated SemVer parser.
- Provide a TryParse-style wrapper that returns a default instead of throwing for untrusted input.
Example fix
// before
var v = new SemanticVersion(rawVersion);
// after
private static readonly Regex Fmt = new(@"^(\d+)\.(\d+)\.(\d+)(?:-([a-z]+)(\d+)?)?$", RegexOptions.IgnoreCase);
static SemanticVersion? ParseSafe(string raw)
{
var core = (raw ?? "").Trim().TrimStart('v').Split('+')[0];
return Fmt.IsMatch(core) ? new SemanticVersion(raw) : null;
} Defensive patterns
Strategy: validation
Validate before calling
private static readonly Regex SemVerFmt = new(@"^(\d+)\.(\d+)\.(\d+)(?:-([a-z]+)(\d+)?)?$", RegexOptions.IgnoreCase);
static bool IsValid(string raw)
{
var core = (raw ?? "").Trim().TrimStart('v').Split('+')[0];
return SemVerFmt.IsMatch(core);
} Try / catch
SemanticVersion v;
try { v = new SemanticVersion(raw); }
catch (ArgumentException) { v = new SemanticVersion("0.0.0"); logger.LogWarning("Unparsable version '{Raw}', defaulting", raw); } Prevention
- Validate with the same regex at the configuration boundary.
- Strip build metadata (after '+') before parsing.
- Document the accepted MAJOR.MINOR.PATCH[-wordNNN] format to users.
- Wrap construction in a TryParse helper for untrusted input.
When it happens
Trigger: Inputs that break the pattern: '1.2' (two parts), '1.2.3.4' (four parts), '1.2.3-alpha.1' (dot in prerelease), '1.2.3-rc-1' (hyphen), '1.2.3+build' (build metadata), '1.2.beta' (non-numeric component), or empty/whitespace string.
Common situations: Parsing full SemVer 2.0 or NuGet-style versions (dotted prerelease, +metadata), plugin manifest versions carrying build metadata, or user-typed version fields that do not match the strict shape.
Related errors
- Invalid hex string.
- {StaticName} returned an unexpected response: {responseStrin
- Translate engine '{options.TranslateEngine}' is not supporte
- Unknown {kind} language '{requested}' for this translate eng
- Offset is empty.
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/c73e817342640d82.
Report an issue: GitHub.