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
- Convert the value to a supported primitive before adding it to the dictionary (e.g. enumValue.ToString(), (long)ulongValue, dateTimeOffset.DateTime).
- Use the strongly typed single-parameter overloads (GetUriWithQueryParameter with int/bool/DateTime/etc.) which are checked at compile time.
- If you need a custom type frequently, project it to a dictionary of supported primitives first.
- 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
- Project values into the supported primitive set before building the dictionary.
- Use the typed single-parameter overloads for compile-time safety.
- Avoid passing object? values of unknown runtime type; narrow the dictionary type at the call site.
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
- Cannot have empty query parameter names.
- The URI ' ' is not a relative URI. When…
- The URI ' ' is not contained by the base URI ' '.
- The URI ' ' is not contained by the base URI ' '.
- ' ' is flagged with SingleDelivery, but the selected…
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)