UriFormatException: Invalid URI: The format of the URI could not be determined. is thrown by new Uri(...) when the string has no scheme and no host, for example "api/v1/" passed as an HttpClient base address. Give the string its full form, http://host:port/path/, with the scheme in front.

For a BaseAddress the string must be absolute: in the test, "http://127.0.0.1:15801/api/v1/" worked and the call returned 200. Check the configuration value the string comes from; a missing http:// or an empty setting gives a UriFormatException with a different detail, shown below.

The error

PS ...\Cli> dotnet run --no-build -- uri-path
Unhandled exception. System.UriFormatException: Invalid URI: The format of the URI could not be determined.
   at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions)
   at System.Uri..ctor(String uriString)
   at Program.<Main>$(String[] args) in ...\Cli\Program.cs:line 114
   at Program.<Main>(String[] args)

The code that threw:

var baseUrl = "api/v1/";
using var http = new HttpClient { BaseAddress = new Uri(baseUrl) };

Why it happens

The Uri(string) constructor used here expects an absolute URI. The stack trace shows the exception comes from that constructor (System.Uri..ctor), before HttpClient is involved at all. Given "api/v1/", a string with no scheme and no host, it reported that it could not determine the format.

Two near misses gave different messages from the same constructor in the same test. A host and port without the scheme:

PS ...\Cli> dotnet run --no-build -- uri
Unhandled exception. System.UriFormatException: Invalid URI: The URI scheme is not valid.
...

That run used var baseUrl = "127.0.0.1:15801/api/v1/";. An empty string:

PS ...\Cli> dotnet run --no-build -- uri-empty
Unhandled exception. System.UriFormatException: Invalid URI: The URI is empty.
...

So the detail after Invalid URI: is worth reading: in these three runs it told apart a bare path, a host and port without http://, and an empty string. The fix for all three is the same, give the constructor the full URL; the fixed run below shows it.

The fix

var baseUrl = "http://127.0.0.1:15801/api/v1/";
using var http = new HttpClient { BaseAddress = new Uri(baseUrl) };
Console.WriteLine(await http.GetStringAsync("patients"));
PS ...\Cli> dotnet run --no-build -- uri-fixed
200 from /api/v1/patients: Maria Garcia, David Chen

With the scheme in place the constructor accepted the string and the client reached the test server. Keep the trailing slash on a base address that has a path; the reason is in the BaseAddress post linked below.

How it was reproduced

A console app (dotnet new console, no packages) on .NET SDK 10.0.403 built an HttpClient with BaseAddress = new Uri(baseUrl) for four values of baseUrl. The fixed run called a minimal API (dotnet new web) on http://127.0.0.1:15801; the three failing runs threw in the Uri constructor, on the line that builds the client, before any request.

Frequently asked

How do I fix Invalid URI: The format of the URI could not be determined?
Pass a full absolute URI with its scheme, such as http://127.0.0.1:15801/api/v1/. In the test, "api/v1/" threw this exception and the full form worked.
Why do I get Invalid URI: The URI scheme is not valid?
In the test that message came from "127.0.0.1:15801/api/v1/", a host and port with no http:// in front.
What does Invalid URI: The URI is empty mean?
The string passed to new Uri() was empty; in the test an empty baseUrl gave exactly that message. Check that the value you read for the base address is set.

More decoded errors in the Fixes category. Slash rules for the base address, tested against the same server, are in An invalid request URI was provided.