dotnet/aspnetcore · error · InvalidOperationException

Cannot format query parameters with values of type

Error message

Cannot format query parameters with values of type '{underlyingParameterValueType}'.

What it means

Thrown by GetFormatterFromParameterValueType when the value type passed to GetUriWithQueryParameters (the dictionary-based overload) is not one of the supported primitive types. The formatter table only covers string, bool, DateTime, DateOnly, TimeOnly, decimal, double, float, Guid, int, long (and their non-Nullable underlyings). Any other type cannot be URL-encoded by this API.

Solutions

  1. Convert the value to a supported primitive before adding it to the dictionary (e.g. enumValue.ToString(), (long)ulongValue, dateTimeOffset.DateTime).
  2. Use the strongly typed single-parameter overloads (GetUriWithQueryParameter with int/bool/DateTime/etc.) which are checked at compile time.
  3. If you need a custom type frequently, project it to a dictionary of supported primitives first.
  4. Avoid passing object? values whose runtime type you do not control; narrow the dictionary value type at the call site.

Example fix

// before: enum value is not in the formatter table
var dict = new Dictionary<string, object?> { ["status"] = OrderStatus.Shipped };
var uri = nav.GetUriWithQueryParameters(dict); // throws

// after: convert to a supported primitive
var dict = new Dictionary<string, object?> { ["status"] = OrderStatus.Shipped.ToString() };
var uri = nav.GetUriWithQueryParameters(dict);
Defensive patterns

Strategy: type-guard

Validate before calling

static readonly HashSet<Type> Supported = new()
{ typeof(string), typeof(bool), typeof(DateTime), typeof(DateOnly), typeof(TimeOnly),
  typeof(decimal), typeof(double), typeof(float), typeof(Guid), typeof(int), typeof(long) };

static bool IsSupportedType(Type t) => Supported.Contains(Nullable.GetUnderlyingType(t) ?? t);

Type guard

static object? ToSupported(object? v) => v switch
{
    null => null,
    Enum e => e.ToString(),
    ulong ul => (long)ul,
    DateTimeOffset dto => dto.DateTime,
    _ when Supported.Contains(v.GetType()) => v,
    _ => Convert.ToString(v, CultureInfo.InvariantCulture)
};

Try / catch

try { uri = nav.GetUriWithQueryParameters(dict); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Cannot format query parameters"))
{ /* convert unsupported values to strings and retry */ }

Prevention

When it happens

Trigger: Calling nav.GetUriWithQueryParameters(dict) where a dictionary value is an object whose runtime type is, e.g., a custom struct, an enum, ulong, uint, byte, char, TimeSpan, DateTimeOffset, or a complex type. Nullable.GetUnderlyingType is applied first, so Nullable<unsupported> also fails.

Common situations: Passing an enum or ulong filter value; passing a POCO by mistake; building the dictionary from a generic source without converting; expecting DateTimeOffset support (only DateTime is supported).

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/080cdc67e62b3661. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/Components/src/NavigationManagerExtensions.cs:723

    {
        var parameterSources = new Dictionary<ReadOnlyMemory<char>, QueryParameterSource>(QueryParameterNameComparer.Instance);

        foreach (var (name, value) in parameters)
        {
            var parameterSource = new QueryParameterSource(name, value);
            parameterSources.Add(parameterSource.EncodedName.AsMemory(), parameterSource);
        }

        return parameterSources;
    }

    private static QueryParameterFormatter<object> GetFormatterFromParameterValueType(Type parameterValueType)
    {
        var underlyingParameterValueType = Nullable.GetUnderlyingType(parameterValueType) ?? parameterValueType;

        if (!_queryParameterFormatters.TryGetValue(underlyingParameterValueType, out var formatter))
        {
            throw new InvalidOperationException(
                $"Cannot format query parameters with values of type '{underlyingParameterValueType}'.");
        }

        return formatter;
    }

    private static bool TryRebuildExistingQueryFromUri(
        string uri,
        out QueryStringEnumerable existingQueryStringEnumerable,
        out ReadOnlySpan<char> hash,
        out QueryStringBuilder newQueryStringBuilder)
    {
        ReadOnlySpan<char> uriWithoutQueryStringAndHash;

        var hashStartIndex = uri.IndexOf('#');
        hash = hashStartIndex < 0 ? "" : uri.AsSpan(hashStartIndex);

        var queryStartIndex = (hashStartIndex > 0 ? uri.AsSpan(0, hashStartIndex) : uri).IndexOf('?');

View on GitHub (pinned to 3600ca084e)