Steps to reproduce
using System;
using System.Threading;
using Npgsql;
class Test2
{
static int Main(string[] args)
{
var connectionString = new NpgsqlConnectionStringBuilder {
Host = "test-server",
Database = "postgres",
Username = "postgres",
Password = "123456",
Pooling = false,
CommandTimeout = 0,
KeepAlive = 30,
TcpKeepAlive = true,
TcpKeepAliveTime = 30
};
var connection = new NpgsqlConnection();
connection.ConnectionString = connectionString.ConnectionString;
connection.Open();
try {
using (var c = new NpgsqlCommand("SELECT 'dummy'", connection)) {
c.ExecuteNonQuery();
}
Console.Write("disconnect the this client from the network and press enter when done so...");
// note: you can also work on localhost and stop the server instead of disconnecting the network
Console.ReadLine();
Console.WriteLine("waiting 1 minute.");
Thread.Sleep(60_000);
Console.WriteLine("BeginTransaction");
connection.BeginTransaction();
}
catch (NpgsqlException ex) {
Console.WriteLine("Expected Exception: " + Environment.NewLine + ex);
}
catch (Exception unexpected) {
Console.WriteLine("Unexpected Exception:" + Environment.NewLine + unexpected);
}
return 0;
}
}
The issue
According to the doc, exceptions related to connection errors should be wrapped in a NpgsqlException exception.
This makes perfectly sense as this will allow catching NpgsqlException at a relatively high level in the code,
dispose all DB related stuff and trying to create a new connection.
However in the example above, an InvalidOperationException will be thrown; this is definitely not an exception that should be handled and ignored at a higher level.
I think it is incorrect to throw a InvalidOperationException and it should be NpgsqlException with possibly containing the IOException. (If the connection would be used again after handling the NpgsqlException, InvalidOperationException would be correct.)
System.InvalidOperationException: Connection is not open
at Npgsql.ThrowHelper.ThrowInvalidOperationException(String message)
at Npgsql.NpgsqlConnection.CheckReady()
at Npgsql.NpgsqlConnection.BeginTransaction(Boolean async, IsolationLevel level, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.BeginTransaction(IsolationLevel level)
at Npgsql.NpgsqlConnection.BeginTransaction()
at Test2.Main(String[] args) in Test2.cs:line 35
Further technical details
Npgsql version: 8.0.2
PostgreSQL version: 16
Operating system: Windows, .NET 6
Steps to reproduce
The issue
According to the doc, exceptions related to connection errors should be wrapped in a NpgsqlException exception.
This makes perfectly sense as this will allow catching NpgsqlException at a relatively high level in the code,
dispose all DB related stuff and trying to create a new connection.
However in the example above, an InvalidOperationException will be thrown; this is definitely not an exception that should be handled and ignored at a higher level.
I think it is incorrect to throw a InvalidOperationException and it should be NpgsqlException with possibly containing the IOException. (If the connection would be used again after handling the NpgsqlException, InvalidOperationException would be correct.)
Further technical details
Npgsql version: 8.0.2
PostgreSQL version: 16
Operating system: Windows, .NET 6