jonh
jonh

Reputation: 254

SqlException: New request is not allowed to start because it should come with valid transaction descriptor

I recently resolved an elusive error with a simple solution. Hopefully this will be of help to someone. My environment:

The symptom was rather bizarre. When navigating to some pages, I would receive the following error:

SqlException: New request is not allowed to start because it should come with valid transaction descriptor.

After first seeing this error, then all other pages would now receive errors, but not the same error. It would alternate between the following two errors:

IndexOutOfRangeException: username2_13_0
    at Microsoft.Data.SqlClient.SqlDataReader.GetOrdinal(string name)

and

IndexOutOfRangeException: id1_14_
    at Microsoft.Data.SqlClient.SqlDataReader.GetOrdinal(string name)

(The strange thing about the above errors is that these columns do exist in the query being executed)

Another interesting anomaly is the fact that the error is only persistent on a connection string to the same database. This is a multi-tenant application and each tenant uses a different database. Only the tenant at which you initially triggered the SqlException: New request is not allowed to start because it should come with valid transaction descriptor. would then receive the persistent IndexOutOfRangeException. This let me to think the connection pool had something to do with the error.

Searching StackOverflow and the web for solutions suggested it has to do with Distributed Transactions (although we do not use distributed transactions) or invalid schema, and several people said the error was related to hibernate/NHibernate and how it managed the transaction.

Upvotes: 0

Views: 454

Answers (1)

jonh
jonh

Reputation: 254

Turns out that the issue had to do with SQL Server's Always Encrypted column-level encryption.

I am using Azure as my key store and using SqlColumnEncryptionAzureKeyVaultProvider as shown below:

var credential = new Azure.Identity.ClientSecretCredential(m3Config.AzureTenantId, m3Config.AzureClientId, m3Config.AzureClientSecret);

SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(credential);

SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders: new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(capacity: 1, comparer: StringComparer.OrdinalIgnoreCase)
{
    {
        SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, akvProvider
    }
});

SqlConnection.ColumnEncryptionKeyCacheTtl = TimeSpan.FromDays(1);

Through trial and error I discovered that my Azure client secret had expired. The issue was resolved by using a non-expired client secret.

The confusing red-herring error message made this very difficult to diagnose.

Upvotes: 2

Related Questions