ThreeMammals/Ocelot · error · FormatException
The ' ' timespan cannot be converted to TimeSpan due to an…
Error message
The '{timespan}' timespan cannot be converted to TimeSpan due to an unknown '{unit}' unit! What it means
After extracting the numeric value, ParseTimespan maps the unit suffix (d, h, m, s, ms; empty = milliseconds) to a TimeSpan via a switch expression. An unrecognized unit suffix throws FormatException. This protects against typos like '1x' or '5sec'.
Solutions
- Change the configured value to an accepted unit: d, h, m, s, ms, or no suffix (milliseconds), e.g. '5min' -> '5m'.
- Remember parsing is case-sensitive: use lowercase units.
- Add startup validation of rate-limit values so the error names the offending route early.
- If you need richer units, extend the switch expression in RateLimitRule.ParseTimespan.
Example fix
// before "Period": "5min" // after "Period": "5m"
Defensive patterns
Strategy: validation
Validate before calling
static readonly string[] Units = { "d", "h", "m", "s", "ms", "" };
bool HasKnownUnit(string p) {
int i = 0; while (i < p.Length && (char.IsDigit(p[i]) || p[i]=='.')) i++;
return Units.Contains(p.Substring(i));
} Try / catch
try { var period = RateLimitRule.PeriodSpan(value); }
catch (FormatException ex) { Error($"Unsupported duration unit in '{value}': {ex.Message}"); throw; } Prevention
- Use only lowercase units: d, h, m, s, ms — or no suffix for milliseconds
- Write '5min' as '5m', '30sec' as '30s'
- Document accepted units wherever rate limits are configured
- Add unit tests covering ParseTimespan suffix parsing
When it happens
Trigger: A Period/Wait config value ends in a suffix outside {d,h,m,s,ms,'' }, e.g. '30sec', '2min', '1hr', '5M' (uppercase M is not accepted as minutes).
Common situations: Human-readable units typed into ocelot.json ('5min'); copy-pasted durations from other libraries; case sensitivity mistakes ('S' vs 's'); localization adding non-standard suffixes.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- The ' ' value doesn't include any digits, so it cannot be…
- ConfigurationRepositoryException(config.Errors)
AI-assisted analysis of ThreeMammals/Ocelot@d1f22d9304 (2026-09-12).
Data as JSON: /api/errors/2fa258cc77e04c46.
Report an issue: GitHub.
Appendix: source
Thrown at src/Configuration/RateLimitRule.cs:86
}
string val = timespan.Trim();
int pos = val.Length;
while (--pos >= 0 && !char.IsDigit(val[pos]) && val[pos] != DecimalSeparator)
{
}
string floating = val[..++pos], unit = val[pos..];
double value = Math.Abs(double.Parse(floating)); // negative values should be disallowed as they could cause everything to malfunction; TODO: Make sense to have validation in src/Ocelot/Configuration/Validator/RouteFluentValidator
return unit.ToLower() switch
{
"d" => TimeSpan.FromDays(value),
"h" => TimeSpan.FromHours(value),
"m" => TimeSpan.FromMinutes(value),
"s" => TimeSpan.FromSeconds(value),
"ms" => TimeSpan.FromMilliseconds(value),
"" => TimeSpan.FromMilliseconds(value), // an unknown unit defaults to milliseconds as the ms unit
_ => throw new FormatException($"The '{timespan}' timespan cannot be converted to {nameof(TimeSpan)} due to an unknown '{unit}' unit!"),
};
}
private static readonly char DecimalSeparator = new NumberFormatInfo().NumberDecimalSeparator[0];
}
View on GitHub (pinned to d1f22d9304)