System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0. — SqlClient was handed a string that is not a connection string at all. In the reproduction it was the connection string's name, "DefaultConnection", passed to UseSqlServer(). Read the value from configuration with GetConnectionString("DefaultConnection") and pass that instead.

The message names index 0, the first character of the string. Here that matched the cause: the whole string was wrong, not one keyword in the middle of a valid connection string.

The error

PS> dotnet run -- bad
...
Unhandled exception. System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0.
   at Microsoft.Data.Common.ConnectionString.DbConnectionOptions.GetKeyValuePair(String connectionString, Int32 currentPosition, StringBuilder buffer, Boolean useOdbcRules, String& keyname, String& keyvalue)
   at Microsoft.Data.Common.ConnectionString.DbConnectionOptions.ParseInternal(Dictionary`2 parsetable, String connectionString, Boolean buildChain, Dictionary`2 synonyms, Boolean firstKey)
...
   at Microsoft.Data.SqlClient.SqlConnection..ctor(String connectionString)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.CreateDbConnection()
...
   at Program.<Main>$(String[] args) in ...\EfInit\Program.cs:line 18

The cuts hide NuGet audit warnings printed by dotnet run and stack frames. Line 18 is db.Database.EnsureCreated(), the first call that needed a connection, not the UseSqlServer() line that received the bad value.

Why it happens

A SQL Server connection string is a list of key=value pairs separated by semicolons. The text DefaultConnection has no =, so the first key-value pair could not be read, and the trace shows the failure in GetKeyValuePair under the SqlConnection constructor. The bad line in the reproduction:

string connectionString = args[0] == "bad"
    ? "DefaultConnection"
    : config.GetConnectionString("DefaultConnection")!;

var options = new DbContextOptionsBuilder<ClinicContext>()
    .UseSqlServer(connectionString)
    .Options;

UseSqlServer() accepted the string without complaint. The exception came later, when EnsureCreated() asked for a connection, which is why the stack trace points somewhere other than the configuration code.

The fix

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=fix8_ef;Trusted_Connection=True"
  }
}
var config = new ConfigurationBuilder()
    .SetBasePath(AppContext.BaseDirectory)
    .AddJsonFile("appsettings.json")
    .Build();
...
    : config.GetConnectionString("DefaultConnection")!;
PS> dotnet run -- good drop
...
Patients: 1
Dropped: True

GetConnectionString("DefaultConnection") reads ConnectionStrings:DefaultConnection from appsettings.json, and with the real value the program created the LocalDB database, saved a patient, counted one row and dropped the database again. The project file copies appsettings.json to the output folder (CopyToOutputDirectory="PreserveNewest"), because the configuration is read from AppContext.BaseDirectory. The value it returned carried three key=value pairs (the server, the database fix8_ef and Trusted_Connection=True), and SqlClient opened the connection with it.

How it was reproduced

A console project from dotnet new console -n EfInit on .NET SDK 10.0.403 with Microsoft.EntityFrameworkCore.SqlServer 10.0.14 (which brought in Microsoft.Data.SqlClient 6.1.7) and Microsoft.Extensions.Configuration.Json 10.0.14. dotnet run -- bad passed the name "DefaultConnection" to UseSqlServer(); dotnet run -- good drop passed the value from configuration against SQL Server LocalDB, database fix8_ef, which the same run deleted.

Frequently asked

What does Format of the initialization string does not conform to specification starting at index 0 mean?
SqlClient could not read the first key=value pair of the connection string. In the reproduction the string was the name DefaultConnection instead of the connection string itself.
Why does the error appear at EnsureCreated or the first query and not at UseSqlServer?
In the reproduction UseSqlServer accepted the bad string and the exception was thrown when EnsureCreated created the SqlConnection, line 18 of the program.
How do I read a connection string from appsettings.json in a console app?
Build a ConfigurationBuilder with AddJsonFile("appsettings.json"), make sure the file is copied to the output folder, and call GetConnectionString("DefaultConnection").

More decoded errors in the Fixes category. A different connection-string mistake, a PostgreSQL string given to SqlClient, is covered in Keyword not supported: 'servername'.