Humanizr/Humanizer · error · ArgumentOutOfRangeException

Unknown byte-size unit system.

Error message

Unknown byte-size unit system.

What it means

Thrown by ByteSize.GetUnits(ByteSizeUnitSystem) for any value that is not DecimalSi or BinaryIec. GetUnits is the internal lookup that maps a unit system to its symbol array; the default arm of the switch rejects undefined enum values rather than returning null.

Source

Thrown at src/Humanizer/Bytes/ByteSize.cs:1180

            result.Append(newValue);
            searchStart = index + oldValue.Length;
            index = CultureInfo.InvariantCulture.CompareInfo.IndexOf(
                searchValue,
                oldValue,
                searchStart,
                CompareOptions.OrdinalIgnoreCase);
        }
        while (index >= 0);

        return result.Append(value, searchStart, value.Length - searchStart).ToString();
    }

    static SystemUnit[] GetUnits(ByteSizeUnitSystem unitSystem) =>
        unitSystem switch
        {
            ByteSizeUnitSystem.DecimalSi => DecimalUnits,
            ByteSizeUnitSystem.BinaryIec => BinaryUnits,
            _ => throw new ArgumentOutOfRangeException(nameof(unitSystem), unitSystem, "Unknown byte-size unit system.")
        };

    static readonly SystemUnit[] DecimalUnits =
    [
        new(BytesInDecimalExabyte, "EB", DataUnit.DecimalExabyte),
        new(BytesInDecimalPetabyte, "PB", DataUnit.DecimalPetabyte),
        new(BytesInDecimalTerabyte, "TB", DataUnit.DecimalTerabyte),
        new(BytesInDecimalGigabyte, "GB", DataUnit.DecimalGigabyte),
        new(BytesInDecimalMegabyte, "MB", DataUnit.DecimalMegabyte),
        new(BytesInDecimalKilobyte, "kB", DataUnit.DecimalKilobyte)
    ];

    static readonly SystemUnit[] BinaryUnits =
    [
        new(BytesInPebibyte, "PiB", DataUnit.BinaryPebibyte),
        new(BytesInTebibyte, "TiB", DataUnit.BinaryTebibyte),
        new(BytesInGibibyte, "GiB", DataUnit.BinaryGibibyte),
        new(BytesInMebibyte, "MiB", DataUnit.BinaryMebibyte),

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Constrain the value to DecimalSi or BinaryIec before formatting; handle Legacy at the call site before reaching GetUnits.
  2. Validate the enum with Enum.IsDefined or an explicit range check upstream.
  3. When deserializing, map unknown values to a default system rather than forwarding them.

Example fix

// before
var units = GetUnits((ByteSizeUnitSystem)userChoice);

// after
var system = userChoice switch
{
    0 => ByteSizeUnitSystem.DecimalSi,
    1 => ByteSizeUnitSystem.BinaryIec,
    _ => ByteSizeUnitSystem.Legacy
};
if (system == ByteSizeUnitSystem.Legacy) { /* use legacy path */ }
Defensive patterns

Strategy: validation

Validate before calling

static ByteSizeUnitSystem NormalizeSystem(ByteSizeUnitSystem value) =>
    value is ByteSizeUnitSystem.DecimalSi or ByteSizeUnitSystem.BinaryIec
        ? value
        : throw new ArgumentOutOfRangeException(nameof(value));

Type guard

static bool IsSupportedUnitSystem(ByteSizeUnitSystem s) =>
    s is ByteSizeUnitSystem.DecimalSi or ByteSizeUnitSystem.BinaryIec;

Try / catch

try { return GetUnits(system); }
catch (ArgumentOutOfRangeException) { throw new ArgumentException("Use DecimalSi or BinaryIec.", nameof(system)); }

Prevention

When it happens

Trigger: Calling a formatting overload that resolves units through GetUnits with a ByteSizeUnitSystem value outside {DecimalSi, BinaryIec} — including an uninitialized/default enum (0 if 0 is not a named member) or a future/invalid cast integer.

Common situations: Casting an arbitrary integer to ByteSizeUnitSystem, deserializing an enum from JSON where the source used a different naming scheme, or passing ByteSizeUnitSystem.Legacy into a path that does not special-case Legacy before GetUnits.

Related errors


AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13). Data as JSON: /api/errors/6597fd450bda4e49. Report an issue: GitHub.