Fixed: "Failed to bind parameter" for an Enum in a Minimal API Query String
?status=Placed worked, and ?status=placed gave a 400 Bad Request with no explanation. The reason was only in the log: Failed to bind parameter "Nullable<OrderStatus> status" from "placed". JSON bodies accept any case here, and query strings don't.
What I Was Doing
My .NET C# Web API on ASP.NET Core 10 has an endpoint with an optional enum in the query string:
g.MapGet("/enum", (OrderStatus? status) => Results.Ok(new { status }));
I called it with the status in lower case:
GET http://localhost:5190/demo/enum?status=placed
What I Expected
The same result as ?status=Placed, since JsonStringEnumConverter accepts any case in a JSON body.
What I Got
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"traceId": "00-3b7e42e64172e7638ebbf246dc598e78-11c712304ca311cf-00"
}
Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to bind parameter "Nullable<OrderStatus> status" from "placed".

What I Checked
The exact name, and a wrong name.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"status": "Placed"
}
Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to bind parameter "Nullable<OrderStatus> status" from "Nope".
So it's strict about case, and it treats a wrong case like a wrong word.
The same value in a JSON body:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"type": "Receipt",
"status": null
}
The docs. The parameter binding page has this exact failure for a number: /products?pageNumber=two gives BadHttpRequestException: Failed to bind parameter "Nullable<int> pageNumber" from "two". Query values go through TryParse, and JSON options don't apply to them.
Why It Happens
For a query string, the binding code parses the text as the enum, with the exact name, and it doesn't read your JSON settings. When parsing fails, the endpoint doesn't run. The response is a plain 400, and the reason goes to the log.
The Fix
If the exact name is good enough, nothing needs fixing, and your API documentation can list the values. When you want any case, and a message that helps the client, accept a string and parse it yourself:
g.MapGet("/enum-string", (string? status) =>
{
if (status is null)
{
return Results.Ok(new { status = (OrderStatus?)null });
}
if (!Enum.TryParse<OrderStatus>(status, ignoreCase: true, out var parsed) || !Enum.IsDefined(parsed))
{
return Results.ValidationProblem(new Dictionary<string, string[]>
{
["status"] = [$"'{status}' isn't a status. Use one of: {string.Join(", ", Enum.GetNames<OrderStatus>())}."],
});
}
return Results.Ok(new { status = (OrderStatus?)parsed });
});
ignoreCase: true allows any case, and Enum.IsDefined refuses numbers that aren't members.
After the Fix
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"status": "Placed"
}
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"status": [
"'Nope' isn't a status. Use one of: Placed, Fulfilled, Cancelled."
]
},
"traceId": "00-8ba9062f0ba8794c433afe39b0599423-005d9387523e7245-00"
}

Common Mistakes
| Mistake | What happens | Do this instead |
|---|---|---|
Adding JsonStringEnumConverter to fix it | It only affects JSON | Parse the string |
Assuming the 400 came from your validation | The endpoint never ran | Read the log |
Dropping Enum.IsDefined | ?status=99 parses | Keep both checks |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Required parameter ... was not provided | The parameter isn't nullable | The header version of this |
?status=1 works | Numbers parse as enums | The fix |
The 400 has no body in production | Problem details aren't set up | Add AddProblemDetails() |
Conclusion
Query strings parse enums by exact name, whatever your JSON settings say. If that's too strict, take a string, parse it with ignoreCase: true, and answer with a message that lists the valid values.
Additional Resources
- Parameter binding in minimal APIs — binding failures.
- Enum.TryParse — the
ignoreCaseoverload.
