Skip to main content

Fixed: "Required parameter was not provided from header" in a Minimal API

· 4 min read
Jagdish Kumawat
Founder @ Dewiride

A request without my header got a 400 Bad Request with an empty explanation, and my endpoint never ran. The log had the reason: Required parameter "string source" was not provided from header. One ? decides whether a header is required.

What I Was Doing​

My .NET C# Web API on ASP.NET Core 10 reads a header with [FromHeader]:

An endpoint
g.MapGet("/header/required", ([FromHeader(Name = "X-Request-Source")] string source) =>
Results.Ok(new { source }));

I called it without the header:

Request
GET http://localhost:5190/demo/header/required

What I Expected​

The endpoint to run, with source empty or null.

What I Got​

Response
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-7eccd113fd241306bbae1c41eeee997d-00182afd897625c4-00"
}
API log
Microsoft.AspNetCore.Http.BadHttpRequestException: Required parameter "string source" was not provided from header.

A response of 400 Bad Request with no details, and the log line BadHttpRequestException: Required parameter "string source" was not provided from header.

What I Checked​

With the header.

Response (with X-Request-Source: mobile-app)
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"source": "mobile-app"
}

So the code's fine, and the header is simply required.

The docs. The parameter binding page explains it for query strings: a parameter that isn't nullable and has no default is required, and leaving it out gives this same BadHttpRequestException. Headers follow the same rule.

Why It Happens​

With nullable reference types on, string means "this is always here", so minimal API binding treats the parameter as required, and refuses the request before your code runs.

The Fix​

Decide what the header is.

Optional: make the parameter nullable, and deal with null:

An endpoint
g.MapGet("/header/optional", ([FromHeader(Name = "X-Request-Source")] string? source) =>
Results.Ok(new { source }));

Required: leave it as it is, and send the header. If clients need a clear message, take a string?, check it, and answer with a 400 that says what's missing.

After the Fix​

Response (no header)
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"source": null
}
Response (with X-Request-Source: mobile-app)
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
"source": "mobile-app"
}

A response of 200 OK with source null when the header is left out, and mobile-app when it's sent.

Common Mistakes​

MistakeWhat happensDo this instead
Expecting null from a string parameterThe request is refused firstUse string?
Debugging the endpointIt never ranRead the log
Leaving out Name = for a header with dashesIt looks for a header named after the parameterGive the name

Troubleshooting​

SymptomLikely causeFix
The header is sent, and it's still refusedA different nameCheck Name =
Failed to bind parameterIt's there, and it can't be parsedThe fix
The same message says query stringIt's a query parameterThe same fix

Conclusion​

A non-nullable [FromHeader] parameter is required, and a missing header gets a 400 before your code runs. Use string? when the header is optional.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.