SECURITY WARNING: Never run commands you don't understand. Always review code before execution. Use at your own risk.
Elixir New Added 19 September 2026

Elixir: (DBConnection.ConnectionError) tcp recv: closed

The database closed a pooled socket that Ecto still believed was usable, so the checkout succeeded and the query died on the wire. The usual culprit is something between the application and the database with an idle timeout: a pgbouncer server_idle_timeout, an RDS proxy, or a cloud load balancer that drops idle flows after a few minutes.

Quick fix

Read the commands before running them. Anything that restarts a service, deletes data or changes permissions should be tried on a non-production system first.

Quick fix
# Keep pooled sockets younger than the shortest idle timeout on the path
config :my_app, MyApp.Repo,
  pool_size: 10,
  idle_interval: 15_000,        # ping idle connections
  queue_target: 50,
  queue_interval: 1000

# What is actually closing it: check the database side first
# Postgres
SHOW idle_in_transaction_session_timeout;
SELECT state, count(*) FROM pg_stat_activity GROUP BY state;
# pgbouncer: server_idle_timeout, server_lifetime, and pool_mode

# Transaction pooling rejects prepared statements, which looks like random closes
config :my_app, MyApp.Repo, prepare: :unnamed

# Long running queries killed by a server timeout give the same message
config :my_app, MyApp.Repo, timeout: 15_000

# Retrying is correct here: the next checkout gets a fresh socket

How to diagnose Elixir errors

Elixir errors are shaped by the actor model: a GenServer.call timeout does not mean the server crashed, it means the server was busy for longer than the caller was willing to wait. The right question is usually "what is that process doing?" rather than "why did the call fail?". Because supervisors restart failed processes automatically, transient errors can also hide in the logs while the system appears healthy.

If the quick fix above does not resolve it, work through these steps. They apply to this whole class of error, not just to this one message, which is usually what saves the time.

  1. Attach to a running node with iex --remsh and inspect the process: Process.info(pid, :message_queue_len). A growing mailbox means the process is the bottleneck.
  2. Use :observer.start() to see the supervision tree, process memory and message queues visually.
  3. Move long-running work out of handle_call. Use handle_cast, a Task, or a dedicated pool so the GenServer stays responsive.
  4. Check restart intensity. A supervisor that exceeds max_restarts takes down its own supervisor, producing a cascade that looks like an unrelated failure at the top.
  5. For compile errors in dependencies, run mix deps.compile --force and check that any required native toolchain (make, gcc, erlang headers) is installed.

Tools worth reaching for

  • :observer.start()
  • iex --remsh
  • Process.info/2
  • mix deps.tree
  • :recon

Authoritative references

Primary documentation for this error, worth reading before applying any fix in production.

hexdocs.pm hexdocs.pm

Related Elixir errors

See all 12 Elixir errors →

Browse other categories

Something missing or wrong?

This entry is maintained by hand. If the fix is out of date, incomplete, or you have a better one, email a correction and it will be reviewed.