Humanizr/Humanizer · error · InvalidOperationException

The configured IFormatter for '{culture?.Name ?? CultureInfo

Error message

The configured IFormatter for '{culture?.Name ?? CultureInfo.CurrentCulture.Name}' does not support fractional seconds. Implement IFractionalTimeSpanFormatter.

What it means

Thrown when formatting a fractional-seconds time part and the culture's IFormatter is neither DefaultFormatter (or ProfiledFormatter) nor an IFractionalTimeSpanFormatter. This means the locale's formatter was not updated to support fractional second output. The culture name is included in the message to identify which locale is affected.

Source

Thrown at src/Humanizer/TimeSpanHumanizeExtensions.cs:440

                    formatter,
                    TimeUnit.Second,
                    SaturateToInt(part.Value),
                    culture,
                    false,
                    toSymbols,
                    null));
                continue;
            }

            if (formatter.GetType() == typeof(DefaultFormatter))
            {
                formattedParts.Add(((DefaultFormatter)formatter).TimeSpanHumanizeWithFractionalSeconds(part.Value, toSymbols));
                continue;
            }

            if (formatter is not IFractionalTimeSpanFormatter fractionalFormatter)
            {
                throw new InvalidOperationException(
                    $"The configured {nameof(IFormatter)} for '{culture?.Name ?? CultureInfo.CurrentCulture.Name}' " +
                    $"does not support fractional seconds. Implement {nameof(IFractionalTimeSpanFormatter)}.");
            }

            formattedParts.Add(fractionalFormatter.TimeSpanHumanizeWithFractionalSeconds(part.Value, toSymbols));
        }

        return ConcatenateTimeSpanParts(formattedParts, culture, collectionSeparator);
    }

    static bool IsBuiltInFractionalTimeSpanFormatter(IFormatter formatter) =>
        formatter.GetType() == typeof(DefaultFormatter) || formatter is ProfiledFormatter;
    static List<FractionalSecondPart> CreateFractionalSecondParts(
        RoundedTimeSpan roundedTimeSpan,
        int precision,
        bool countEmptyUnits,
        TimeUnit maxUnit)
    {

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Implement IFractionalTimeSpanFormatter on your custom formatter class.
  2. Use a built-in DefaultFormatter or ProfiledFormatter for the affected culture.
  3. Avoid fractional-seconds humanize for cultures whose formatter doesn't support it.

Example fix

// before
public class MyFormatter : IFormatter { /* no fractional support */ }

// after
public class MyFormatter : IFormatter, IFractionalTimeSpanFormatter
{
    public string TimeSpanHumanizeWithFractionalSeconds(decimal seconds, bool toSymbols) => ...
}
Defensive patterns

Strategy: type-guard

Validate before calling

static bool FormatterSupportsFractional(IFormatter formatter, CultureInfo? culture) =>
    formatter is IFractionalTimeSpanFormatter ||
    formatter.GetType() == typeof(DefaultFormatter) ||
    formatter is ProfiledFormatter;

Type guard

static bool CanFormatFractional(IFormatter formatter) =>
    formatter is IFractionalTimeSpanFormatter ||
    formatter is ProfiledFormatter;

Prevention

When it happens

Trigger: Calling HumanizeWithFractionalSeconds with a culture whose registered formatter doesn't implement IFractionalTimeSpanFormatter, and the TimeSpan has a visible fractional seconds component. Common with custom or incomplete locale formatters.

Common situations: Using a custom IFormatter registered for a specific locale that lacks fractional-seconds support. A locale profile that was authored before fractional seconds were introduced. Mixing a built-in strategy with a third-party formatter.

Related errors


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