Misleading Error "invalid encoding name: unicode" Thrown When Setting Client Encoding After Database Connection Lost

Issue #267 resolved
Declan McGrath
created an issue

Problem: I think that a connection error should be thrown when the database connection is lost and set_client_encoding() is called, not an "invalid encoding name: unicode" error - as this makes no sense, unicode is an extremely valid encoding name :-)

Minimal Test Case

Just change the connection parameters and ensure that the byebug gem is installed. Then run this...

require 'pg'                                                                                                            

require 'byebug'; debugger                                                                                              
# Now start the postgres server with: sudo service postgresql start                                                     

connection_parameters = {                                                                                               
    :user=>"someuser",                                                                                                  
    :password=>"somepass",                                                                                              
    :dbname=>"somedb",                                                                                           
    :host=>"localhost",                                                                                                 
    :port=>5432                                                                                                         
}                                                                                                                       
conn = PG.connect(connection_parameters)                                                                                
$stderr.puts '---',                                                                                                     
    RUBY_DESCRIPTION,                                                                                                   
    PG.version_string( true ),                                                                                          
    "Server version: #{conn.server_version}",                                                                           
    "Client version: #{PG.respond_to?( :library_version ) ? PG.library_version : 'unknown'}",                           
    '---'                                                                                                               

require 'byebug'; debugger                                                                                              
# Now stop the postgres server with  sudo service postgresql stop                                                       
conn.set_client_encoding('unicode') # Problem: This line throws a confusing error                                       

result = conn.exec( "SELECT * from pg_stat_activity" )                                                                  
$stderr.puts %Q{Expected this to throw an error that indicates the database server is down}                             
p result.field_values( 'state' ) 

Error

The above produces the following error...

pg_problem.rb:24:in `set_client_encoding': invalid encoding name: unicode (PG::Error)
        from pg_problem.rb:24:in `<main>'

I presume that the expected behaviour is that a connection error is thrown?

Backtrace Example From a Rails App

This error can occur in a Rails app. Here an the example stacktrace...

.rvm/gems/ruby-2.3.1/gems/activerecord-5.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb
   682:         # Configures the encoding, verbosity, schema search path, and time zone of the connection.
   683:         # This is called by #connect and should not be called manually.
   684:         def configure_connection
   685:           if @config[:encoding]
   686:               require 'byebug'; debugger
=> 687:             @connection.set_client_encoding(@config[:encoding])
   688:           end
   689:           self.client_min_messages = @config[:min_messages] || 'warning'
   690:           self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
   691: 
(byebug) @connection
#<PG::Connection:0x000000039e0a18>
(byebug) @connection.status
1
(byebug) c

PG::Error (invalid encoding name: unicode):

activerecord (5.0.1) lib/active_record/connection_adapters/postgresql_adapter.rb:687:in `set_client_encoding'
activerecord (5.0.1) lib/active_record/connection_adapters/postgresql_adapter.rb:687:in `configure_connection'
activerecord (5.0.1) lib/active_record/connection_adapters/postgresql_adapter.rb:255:in `reconnect!'
activerecord (5.0.1) lib/active_record/connection_adapters/abstract_adapter.rb:423:in `verify!'
activerecord (5.0.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:778:in `block in checkout_and_verify'
activesupport (5.0.1) lib/active_support/callbacks.rb:126:in `call'
activesupport (5.0.1) lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
activesupport (5.0.1) lib/active_support/callbacks.rb:455:in `call'
activesupport (5.0.1) lib/active_support/callbacks.rb:101:in `__run_callbacks__'
activesupport (5.0.1) lib/active_support/callbacks.rb:750:in `_run_checkout_callbacks'
activerecord (5.0.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:777:in `checkout_and_verify'
activerecord (5.0.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:490:in `checkout'
activerecord (5.0.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:364:in `connection'
activerecord (5.0.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:883:in `retrieve_connection'
activerecord (5.0.1) lib/active_record/connection_handling.rb:128:in `retrieve_connection'
activerecord (5.0.1) lib/active_record/connection_handling.rb:91:in `connection'
activerecord (5.0.1) lib/active_record/migration.rb:559:in `connection'
activerecord (5.0.1) lib/active_record/migration.rb:546:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
activesupport (5.0.1) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
activesupport (5.0.1) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
activesupport (5.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.1) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
web-console (3.3.0) lib/web_console/middleware.rb:131:in `call_app'
web-console (3.3.0) lib/web_console/middleware.rb:20:in `block in call'
web-console (3.3.0) lib/web_console/middleware.rb:18:in `catch'
web-console (3.3.0) lib/web_console/middleware.rb:18:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'

Comments (3)

  1. Lars Kanis

    @Declan McGrath thanks for reporting this!

    The error message is misleading. I'll fix this.

    Unfortunately this is a call which is directly mapped to the corresponding libpq function PQsetClientEncoding and this function doesn't distinguish between connection error and invalid encoding. Insofar I would just reword the error text.

  2. Log in to comment