Other 4xx codes
All HTTP status codes in ASP.NET Core
4xx Client error
The server has no resource at this URL, or does not want to say it has one.
In ASP.NET Core: Return it when an ID does not exist. Routing returns it when no endpoint matches.
The StatusCodes constant, HttpStatusCode enum name, reason phrase, class, and how EnsureSuccessStatusCode() and the standard resilience handler treat 404.
| Constant | StatusCodes.Status404NotFound |
|---|---|
| HttpStatusCode | HttpStatusCode.NotFound |
| Reason phrase | Kestrel sends Not Found |
| Class | 4xx, client error |
| IsSuccessStatusCode | false |
| EnsureSuccessStatusCode() | throws HttpRequestException: Response status code does not indicate success: 404 (Not Found). |
| Standard resilience handler | does not retry it |
TypedResults.NotFound()
TypedResults.NotFound<TValue>(value)
Results.StatusCode(StatusCodes.Status404NotFound)
Results.Problem(statusCode: StatusCodes.Status404NotFound, detail: "...")NotFound()
NotFound(value)
StatusCode(StatusCodes.Status404NotFound)
Problem(statusCode: StatusCodes.Status404NotFound, detail: "...")What Results.Problem(statusCode: 404) sends (with AddProblemDetails()), as application/problem+json:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"traceId": "0HNA1B2C3D4E5:00000001"
}A controller's Problem(statusCode: 404) sends the same body.
A bare StatusCode(404) in an [ApiController] also gets a ProblemDetails body automatically; Results.StatusCode(404) in a minimal API sends an empty body unless you add UseStatusCodePages().
Setup
app.MapGet("/items", () => "items");Request
GET /nope HTTP/1.1Response (recorded)
HTTP/1.1 404 Not FoundRouting finds nothing and the response is 404 with an empty body, even in an API that uses ProblemDetails everywhere else.
Fix: Add AddProblemDetails() and UseStatusCodePages(); see the next example.
Setup
builder.Services.AddProblemDetails();
app.UseExceptionHandler();
app.UseStatusCodePages();Request
GET /nope HTTP/1.1Response (recorded)
HTTP/1.1 404 Not Found
Content-Type: application/problem+json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"traceId": "0HNA1B2C3D4E5:00000001"
}With AddProblemDetails, UseStatusCodePages writes a ProblemDetails body for empty error responses.
Setup
app.MapGet("/items/{id:int}", (int id) => id);Request
GET /items/abc HTTP/1.1Response (recorded)
HTTP/1.1 404 Not FoundRoute constraints decide whether the route matches at all. "abc" is not an int, so there is no match and the answer is 404, not 400.
Fix: Use constraints to choose between routes, not to validate input. Without :int, "abc" fails binding and gives 400.
Setup
[HttpGet("missing")]
public IActionResult Missing() => NotFound();Request
GET /api/things/missing HTTP/1.1Response (recorded)
HTTP/1.1 404 Not Found
Content-Type: application/problem+json; charset=utf-8
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"traceId": "0HNA1B2C3D4E5:00000001"
}[ApiController] turns error status codes without a body into ProblemDetails automatically. Minimal APIs do not (see the StatusCode example on this page).
Every response on this page was recorded from ASP.NET Core 10.0.12 on Kestrel in the Production environment; the HttpClient rows come from .NET 10.0.12 and Microsoft.Extensions.Http.Resilience 10.10.0.
All HTTP status codes in ASP.NET Core