SQLSTATE 55P03 ERROR Class 55: Object Not In Prerequisite State

lock_not_available canceling statement due to lock timeout — 55P03

PostgreSQL error "canceling statement due to lock timeout" (SQLSTATE 55P03): what it means, common causes, and how to fix it.

PG 12, 13, 14, 15, 16, 17, 18 Official docs
Last reviewed May 2025 Grounded in source

Diagnostic Queries

Symptoms

A statement waited for a lock longer than lock_timeout and was cancelled. PostgreSQL raises SQLSTATE 55P03 (lock_not_available).

  • Only happens when lock_timeout is set (default 0 = wait forever).
  • The statement is cancelled while blocked, not while running.
  • Common guard for DDL that must not wait behind long transactions.

What the server log shows

ERROR:  canceling statement due to lock timeout

Why PostgreSQL raises this — what the manual says

Section 19.11.1 Statement Behavior (lock_timeout):

“Abort any statement that waits longer than the specified amount of time while attempting to acquire a lock on a table, index, row, or other database object.”

While blocked waiting to acquire a lock, the backend checks elapsed wait time against lock_timeout. If it exceeds the limit, the wait is abandoned and the statement is cancelled with 55P03.

Common causes

  • A long-running transaction holding a conflicting lock.
  • DDL blocked behind active queries on the same table.
  • An intentionally short lock_timeout guard around migrations.

Relevant GUC parameters

Parameter Default Effect
lock_timeout 0 Max time to wait for a lock before cancelling (0 = wait forever).
deadlock_timeout 1s How long to wait before checking for a deadlock.

How to fix it

  1. Find and resolve the blocking session (commit/cancel it).
  2. Retry the statement after the blocker releases its lock.
  3. Keep transactions short; run DDL during low-traffic windows with a sensible lock_timeout.

Diagnostic query

-- Who holds the lock we are waiting on?
SELECT blocked.pid AS blocked_pid, blocking.pid AS blocking_pid,
       blocking.query AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
  ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
WHERE blocked.wait_event_type = 'Lock';

Related & next steps

Reference: PostgreSQL 18 Section 20.10 “Statement Behavior”.

Was this helpful?