{"record":{"id":"080cdc67e62b3661","repo":"dotnet/aspnetcore","slug":"cannot-format-query-parameters-with-values-of-type","errorCode":null,"errorMessage":"Cannot format query parameters with values of type '{underlyingParameterValueType}'.","messagePattern":"Cannot format query parameters with values of type '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/NavigationManagerExtensions.cs","lineNumber":723,"sourceCode":"    {\n        var parameterSources = new Dictionary<ReadOnlyMemory<char>, QueryParameterSource>(QueryParameterNameComparer.Instance);\n\n        foreach (var (name, value) in parameters)\n        {\n            var parameterSource = new QueryParameterSource(name, value);\n            parameterSources.Add(parameterSource.EncodedName.AsMemory(), parameterSource);\n        }\n\n        return parameterSources;\n    }\n\n    private static QueryParameterFormatter<object> GetFormatterFromParameterValueType(Type parameterValueType)\n    {\n        var underlyingParameterValueType = Nullable.GetUnderlyingType(parameterValueType) ?? parameterValueType;\n\n        if (!_queryParameterFormatters.TryGetValue(underlyingParameterValueType, out var formatter))\n        {\n            throw new InvalidOperationException(\n                $\"Cannot format query parameters with values of type '{underlyingParameterValueType}'.\");\n        }\n\n        return formatter;\n    }\n\n    private static bool TryRebuildExistingQueryFromUri(\n        string uri,\n        out QueryStringEnumerable existingQueryStringEnumerable,\n        out ReadOnlySpan<char> hash,\n        out QueryStringBuilder newQueryStringBuilder)\n    {\n        ReadOnlySpan<char> uriWithoutQueryStringAndHash;\n\n        var hashStartIndex = uri.IndexOf('#');\n        hash = hashStartIndex < 0 ? \"\" : uri.AsSpan(hashStartIndex);\n\n        var queryStartIndex = (hashStartIndex > 0 ? uri.AsSpan(0, hashStartIndex) : uri).IndexOf('?');","sourceCodeStart":705,"sourceCodeEnd":741,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/NavigationManagerExtensions.cs#L705-L741","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before: enum value is not in the formatter table\nvar dict = new Dictionary<string, object?> { [\"status\"] = OrderStatus.Shipped };\nvar uri = nav.GetUriWithQueryParameters(dict); // throws\n\n// after: convert to a supported primitive\nvar dict = new Dictionary<string, object?> { [\"status\"] = OrderStatus.Shipped.ToString() };\nvar uri = nav.GetUriWithQueryParameters(dict);","handlingStrategy":"type-guard","validationCode":"static readonly HashSet<Type> Supported = new()\n{ typeof(string), typeof(bool), typeof(DateTime), typeof(DateOnly), typeof(TimeOnly),\n  typeof(decimal), typeof(double), typeof(float), typeof(Guid), typeof(int), typeof(long) };\n\nstatic bool IsSupportedType(Type t) => Supported.Contains(Nullable.GetUnderlyingType(t) ?? t);","typeGuard":"static object? ToSupported(object? v) => v switch\n{\n    null => null,\n    Enum e => e.ToString(),\n    ulong ul => (long)ul,\n    DateTimeOffset dto => dto.DateTime,\n    _ when Supported.Contains(v.GetType()) => v,\n    _ => Convert.ToString(v, CultureInfo.InvariantCulture)\n};","tryCatchPattern":"try { uri = nav.GetUriWithQueryParameters(dict); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Cannot format query parameters\"))\n{ /* convert unsupported values to strings and retry */ }","preventionTips":["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."],"tags":["blazor","querystring","type-conversion","uri"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}