Humanizr/Humanizer · error · FormatException
A byte-size format can contain only one distinct unit token.
Error message
A byte-size format can contain only one distinct unit token.
What it means
Thrown by ByteSize.FindFormatUnit when the masked format selects two distinct higher-order unit tokens with different DataUnit values (for example both 'MB' and 'GB' in the same decimal format, or 'MiB' and 'GiB' in a binary format). A byte-size format may name exactly one scaling unit.
Source
Thrown at src/Humanizer/Bytes/ByteSize.cs:1048
}
if (maskedFormat.Contains("EiB", StringComparison.OrdinalIgnoreCase))
{
throw new FormatException("EiB is outside the range supported by ByteSize.Bits.");
}
SystemUnit? selectedUnit = null;
var remainingFormat = maskedFormat;
foreach (var unit in units)
{
if (!remainingFormat.Contains(unit.Symbol, StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (selectedUnit is not null && selectedUnit.Value.DataUnit != unit.DataUnit)
{
throw new FormatException("A byte-size format can contain only one distinct unit token.");
}
selectedUnit = unit;
remainingFormat = ReplaceOrdinalIgnoreCase(
remainingFormat,
unit.Symbol,
new(' ', unit.Symbol.Length));
}
var containsBytes = remainingFormat.Contains(ByteSymbol, StringComparison.Ordinal);
var containsBits = remainingFormat.Contains(BitSymbol, StringComparison.Ordinal);
var tokenCount = (selectedUnit is null ? 0 : 1) + (containsBytes ? 1 : 0) + (containsBits ? 1 : 0);
if (tokenCount > 1)
{
throw new FormatException("A byte-size format can contain only one distinct unit token.");
}
if (selectedUnit is not null)View on GitHub (pinned to ffc2b77c0f)
Solutions
- Use a single unit token per format string; render the second quantity in a separate ToString call.
- If you need a ratio, compute the numbers yourself and interpolate them into a plain string.
- Quote one of the tokens as a literal ("MB") if it is meant as decoration rather than the active unit.
Example fix
// before
var text = $"{used.ToString("#.## GB")} / {total.ToString("#.## GB")}"; // accidentally merged into one format
// after
var text = $"{used.ToString("#.## GB")} / {total.ToString("#.## GB")}"; // two separate calls Defensive patterns
Strategy: validation
Validate before calling
static void EnsureSingleScalingUnit(string format, SystemUnit[] units)
{
var matches = units.Count(u => format.Contains(u.Symbol, StringComparison.OrdinalIgnoreCase));
if (matches > 1) throw new ArgumentException("Format contains more than one scaling unit token.");
} Try / catch
try { return size.ToString(format); }
catch (FormatException) { throw new ArgumentException("Use exactly one scaling unit token per format.", nameof(format)); } Prevention
- One scaling unit per format string
- Render ratios as two separate ToString calls
- Quote extra unit-like letters as literals
When it happens
Trigger: Passing a format string like "#.## MB GB" or "# GiB MiB" to ByteSize.ToString. The loop over the active unit array sets selectedUnit, and on the next match with a different DataUnit it throws.
Common situations: Building a format string by concatenating two template fragments, templating errors where a placeholder leaks a unit token, or attempting to render a ratio like 'X MB per Y GB' in a single ToString call instead of two.
Related errors
- Unit token '{unit.Symbol}' does not belong to the selected b
- Value is not in the correct format
- EiB is outside the range supported by ByteSize.Bits.
- Unable to protect the byte-size unit token.
- Unknown byte-size unit system.
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/030e58b28348e03c.
Report an issue: GitHub.