Common Issues and Solutions

Dan Lynch

Dan Lynch

Nov 17, 2025

lesson header image

This guide covers common issues you might encounter while using pgpm and how to fix them quickly.

Table of Contents

Postgres Issues

Docker not running

Symptom:

Cannot connect to the Docker daemon

Solution:

Start Docker Desktop and ensure it's running before executing pgpm docker start.

Postgres not accepting connections

Symptom:

psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed

Solution:

# Check if Postgres is running
pgpm docker start

# Load environment variables
eval "$(pgpm env)"

# Verify connection
psql -c "SELECT version();"

Testing Issues

Tests fail to connect to database

Symptom: Tests time out or fail with connection errors

Solution: Ensure Postgres is running and users are bootstrapped:

pgpm docker start
eval "$(pgpm env)"
pgpm admin-users bootstrap --yes

Current transaction is aborted in tests

Symptom:

When testing operations that should fail (RLS violations, permission errors, constraint violations), subsequent queries on the same connection fail with:

current transaction is aborted, commands ignored until end of transaction block

The Problem:

In Postgres, any error inside a transaction marks the entire transaction as aborted. After that, every further query on that connection fails until you explicitly end the transaction.

This is particularly painful in tests where you intentionally assert failures (e.g., expect(...).rejects.toThrow(...)) and then want to continue using the same db connection.

Solution: Use Savepoints

Wrap each "expected-to-fail" operation in a savepoint, and roll back to that savepoint after the failure. This clears the error state while keeping the surrounding transaction open.

Pattern:

const point = 'some_savepoint';
await db.savepoint(point);

await expect(
  db.query(/* statement that should fail */)
).rejects.toThrow(/permission denied/);

await db.rollback(point); // ROLLBACK TO SAVEPOINT

Example: Anonymous users cannot modify data

it('anonymous users cannot modify any data', async () => {
  db.setContext({ role: 'anonymous' });

  const insertPoint = 'anonymous_insert';
  await db.savepoint(insertPoint);
  await expect(
    db.query(`
      INSERT INTO pets.pets (name, species, owner_id)
      VALUES ('Anonymous Pet', 'hamster', $1)
    `, [alice])
  ).rejects.toThrow(/permission denied/);
  await db.rollback(insertPoint);

  const updatePoint = 'anonymous_update';
  await db.savepoint(updatePoint);
  await expect(
    db.query(`UPDATE pets.pets SET name = 'Hacked'`)
  ).rejects.toThrow(/permission denied/);
  await db.rollback(updatePoint);

  const deletePoint = 'anonymous_delete';
  await db.savepoint(deletePoint);
  await expect(
    db.query(`DELETE FROM pets.pets`)
  ).rejects.toThrow(/permission denied/);
  await db.rollback(deletePoint);
});

By using savepoints + rollback, you can:

  • Assert failures safely
  • Keep using the same db transaction
  • Avoid current transaction is aborted errors entirely

For more details, see Advanced: Handling Exceptions and Aborted Transactions.

Environment Variable Issues

Environment variables not set

Symptom: Commands fail with "PGHOST not set" or similar

Solution: Load pgpm environment:

eval "$(pgpm env)"

To make permanent, add to your shell config:

# Add to ~/.bashrc or ~/.zshrc
eval "$(pgpm env)"
Previous Lesson