↑↓ select↵ open⌫ change scopeOpen full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

Wiki / SQLSTATE

F0001 — lock_file_exists

F0001 is a startup ownership failure. PostgreSQL checks both the lock file and the shared-memory identity for the intended data directory; a live owner is different from a stale artifact left by a crashed postmaster.

English manual coverage begins with PostgreSQL 8.1. Source history and runtime observations have their own recorded version boundaries.

Reading PG 18·Select a recorded version

aliases
Unknown
class name
Configuration File Error
condition name
lock_file_exists
lang
en
sqlstate
F0001

Definition PG 18

F0001

At a glance {#at-a-glance}

F0001 is a startup ownership failure. PostgreSQL checks both the lock file and the shared-memory identity for the intended data directory; a live owner is different from a stale artifact left by a crashed postmaster.

Meaning {#meaning}

CreateLockFile creates the lock file atomically with O_EXCL. If an existing file contains a PID, it uses kill(pid, 0) to distinguish a live process from a vanished one. For the data-directory lock it also reads the recorded shared-memory identifiers and calls PGSharedMemoryIsInUse; that helper only treats a segment associated with the intended DataDir as relevant, because accidental shared-memory ID matches are possible. An empty lock file is a separate F0001 branch and can mean that another server is still starting or that a previous startup crashed.

The SysV shared-memory startup path has the same boundary: an attached or indeterminate pre-existing segment is reported as still in use, while an unattached segment associated with the data directory can be removed and recreated. These guards prevent two postmasters from claiming one cluster.

Messages {#messages}

  • FATAL, SQLSTATE F0001: lock file "%s" already exists.
    • Data-directory hint: Is another postgres (PID %d) running in data directory "%s"? (the postmaster wording is selected for the encoded owner).
    • Socket-lock variants name using socket file "%s" instead.
  • FATAL, SQLSTATE F0001: lock file "%s" is empty.
    • Hint: Either another server is starting, or the lock file is the remnant of a previous server startup crash.
  • FATAL, SQLSTATE F0001: pre-existing shared memory block (key %lu, ID %lu) is still in use.
    • Hint: Terminate any old server processes associated with data directory "%s".

Other lock-file I/O failures use errcode_for_file_access() and can receive a different SQLSTATE; do not collapse them into F0001.

Diagnosis {#diagnosis}

Confirm the exact PGDATA, socket directory, PID, start time, recorded device/inode identity, process owner, and postmaster log. A successful kill(pid, 0), or a failure whose errno is neither ESRCH nor EPERM, keeps the live-process branch active. ESRCH means that the PID does not exist; EPERM means that a process exists but the caller lacks permission to signal it. This guard treats EPERM as a candidate for the next identity checks because checkDataDir() and the 0600/0640 lock-file modes rule out a different-UID process as the competing postmaster; it does not by itself authorize deleting the lock. If the PID is gone or treated as a different-UID candidate, inspect the data-directory shared-memory IDs and whether an orphan backend still attaches before considering cleanup. An empty file is explicitly ambiguous, not proof of staleness.

Response {#response}

This is a startup FATAL, so there is no client transaction state to recover; after the ownership problem is resolved, start the server and use a new connection. If another postmaster or backend is live, stop or coordinate it through normal administration. Only after verifying the exact cluster, process identity, and shared-memory state may an operator follow the documented stale-lock cleanup path. Never remove a lock or shared-memory object by pathname, PID text, or numeric ID alone; if the owner is live, deletion risks split-brain (two postmasters claiming one cluster) and data loss.

Versions {#versions}

The locked catalogue records this condition from 7.4; fixed startup and shared-memory paths are from PostgreSQL 18.6. No process, lock-file, or shared-memory fault was induced for this source-only entry.

Related {#related}

F0000, 57P03, 58P01

Sources {#sources}

src/backend/utils/init/miscinit.c#L1262-L1427

src/backend/port/sysv_shmem.c#L306-L335

src/backend/port/sysv_shmem.c#L765-L835

The structured evidence record records live/stale guards, fixed FATAL messages, and the source/runtime boundary.

Compare versions

SQLSTATE evidence and recorded runtime versions

claims · identity
{
  "claim_id": "identity",
  "limits": "",
  "method": "Read locked definition snapshot.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "F0001 is lock_file_exists in SQLSTATE Class F0."
}
claims · resolved-paths
{
  "claim_id": "resolved-paths",
  "limits": "Source confirmation is not natural runtime.",
  "method": "Read complete PID, shared-memory identity, and startup cleanup guards.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.path.0",
    "src.path.1"
  ],
  "statement": "Startup distinguishes a live lock owner, an empty or stale lock, and shared memory associated with the intended data directory; only the live/in-use branches emit the fixed F0001 FATAL messages."
}
claims · history
{
  "claim_id": "history",
  "limits": "",
  "method": "Use locked catalogue boundary.",
  "position": 2,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "The locked catalogue records F0001 from 7.4; it does not prove the exact introduction rationale."
}
messages · message.0
{
  "limits": "",
  "message_id": "message.0",
  "path": "",
  "position": 0,
  "raw": {
    "hint_template": "Is another postgres (PID %d) running in data directory \"%s\"?",
    "hint_variants": [
      "Is another postmaster (PID %d) running in data directory \"%s\"?",
      "Is another postgres (PID %d) using socket file \"%s\"?",
      "Is another postmaster (PID %d) using socket file \"%s\"?"
    ],
    "id": "message.0",
    "primary_template": "lock file \"%s\" already exists",
    "severity_source": "FATAL",
    "sources": [
      "src.path.0"
    ],
    "sqlstate": "F0001"
  },
  "severity": "FATAL",
  "sources": [
    "src.path.0"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "lock file \" \" already exists",
      "position": 0,
      "role": "",
      "template": "lock file \"%s\" already exists"
    },
    {
      "kind": "hint",
      "literal": "Is another postgres (PID ) running in data directory \" \"?",
      "position": 1,
      "role": "",
      "template": "Is another postgres (PID %d) running in data directory \"%s\"?"
    },
    {
      "kind": "hint",
      "literal": "Is another postmaster (PID ) running in data directory \" \"?",
      "position": 2,
      "role": "",
      "template": "Is another postmaster (PID %d) running in data directory \"%s\"?"
    },
    {
      "kind": "hint",
      "literal": "Is another postgres (PID ) using socket file \" \"?",
      "position": 3,
      "role": "",
      "template": "Is another postgres (PID %d) using socket file \"%s\"?"
    },
    {
      "kind": "hint",
      "literal": "Is another postmaster (PID ) using socket file \" \"?",
      "position": 4,
      "role": "",
      "template": "Is another postmaster (PID %d) using socket file \"%s\"?"
    }
  ]
}
messages · message.1
{
  "limits": "",
  "message_id": "message.1",
  "path": "",
  "position": 1,
  "raw": {
    "hint_template": "Either another server is starting, or the lock file is the remnant of a previous server startup crash.",
    "id": "message.1",
    "primary_template": "lock file \"%s\" is empty",
    "severity_source": "FATAL",
    "sources": [
      "src.path.0"
    ],
    "sqlstate": "F0001"
  },
  "severity": "FATAL",
  "sources": [
    "src.path.0"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "lock file \" \" is empty",
      "position": 0,
      "role": "",
      "template": "lock file \"%s\" is empty"
    },
    {
      "kind": "hint",
      "literal": "Either another server is starting, or the lock file is the remnant of a previous server startup crash.",
      "position": 1,
      "role": "",
      "template": "Either another server is starting, or the lock file is the remnant of a previous server startup crash."
    }
  ]
}
messages · message.2
{
  "limits": "",
  "message_id": "message.2",
  "path": "",
  "position": 2,
  "raw": {
    "hint_template": "Terminate any old server processes associated with data directory \"%s\".",
    "id": "message.2",
    "primary_template": "pre-existing shared memory block (key %lu, ID %lu) is still in use",
    "severity_source": "FATAL",
    "sources": [
      "src.path.0",
      "src.path.1"
    ],
    "sqlstate": "F0001"
  },
  "severity": "FATAL",
  "sources": [
    "src.path.0",
    "src.path.1"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "pre-existing shared memory block (key u, ID u) is still in use",
      "position": 0,
      "role": "",
      "template": "pre-existing shared memory block (key %lu, ID %lu) is still in use"
    },
    {
      "kind": "hint",
      "literal": "Terminate any old server processes associated with data directory \" \".",
      "position": 1,
      "role": "",
      "template": "Terminate any old server processes associated with data directory \"%s\"."
    }
  ]
}
sources · src.errcodes.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/errcodes.txt",
  "position": 0,
  "sha256": "6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba",
  "source_id": "src.errcodes.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt#L454"
}
sources · src.path.0
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/init/miscinit.c",
  "position": 1,
  "sha256": "54bdb859c143a6c70d86067ccf2e124f59aa0852e5705bb653652e41a60af39a",
  "source_id": "src.path.0",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/init/miscinit.c#L1262"
}
sources · src.path.1
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/port/sysv_shmem.c",
  "position": 2,
  "sha256": "150a1143ebffbc726243cb1925109b3237173100814633ee3822f4470ca488de",
  "source_id": "src.path.1",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/port/sysv_shmem.c#L306"
}

Source references

Full definition and evidence JSON

Definition sources

center · PostgreSQL 18 · english-manuals:f648381640bf00f42cebe299bfbb2e4648eefa1b71e1c1193cbdb6dd556963ae

Text language: en · english-manuals:f648381640bf00f42cebe299bfbb2e4648eefa1b71e1c1193cbdb6dd556963ae