Skip to content

58P01 — undefined_file

Source-backed full reference for PostgreSQL SQLSTATE 58P01.

58P01

At a glance

58P01 means that a required file or directory could not be found. In the fixed tablespace path, PostgreSQL distinguishes an ENOENT target during chmod from other permission or filesystem failures; the recovery hint is conditional on the server being in recovery.

Field Value
SQLSTATE 58P01
Condition undefined_file
Status active
Known present by 7.4
Locked snapshots 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3
Macros ERRCODE_UNDEFINED_FILE
Aliases

Meaning

utility.c calls PreventInTransactionBlock(isTopLevel, "CREATE TABLESPACE") before entering CreateTableSpace, so the command is rejected inside an explicit transaction block; there is no explicit client transaction block to roll back for that command. create_tablespace_directories() is used after that command and from tablespace WAL replay. When the target is not an in-place directory and chmod(location, ...) returns ENOENT, the code emits SQLSTATE 58P01 with directory "%s" does not exist. It adds Create this directory for the tablespace before restarting the server. only when InRecovery is true. Other chmod failures use errcode_for_file_access() and the dynamic primary could not set permissions on directory "%s": %m; an in-place creation failure similarly uses could not create directory "%s": %m with an errno-selected code.

The condition is therefore broader than tablespace startup. The operation and %m detail decide whether the missing object is a tablespace, relation file, configuration file, or another file consumer.

Messages

  • ERROR, SQLSTATE 58P01: directory "%s" does not exist
    • Conditional hint during recovery: Create this directory for the tablespace before restarting the server.
  • ERROR, with errcode_for_file_access(): could not set permissions on directory "%s": %m.
  • ERROR, with errcode_for_file_access(): could not create directory "%s": %m (the in-place directory branch).

The latter two templates are not guaranteed to be 58P01: errcode_for_file_access() selects the SQLSTATE from the saved errno.

Diagnosis

Record the complete primary, %m detail, phase, path, database/tablespace identity, and whether the caller is SQL execution or WAL replay. Check that the expected volume is mounted at the exact path, then verify ownership, mode, symlink target, and the tablespace version directory. A missing mount and an intentionally removed directory need different recovery plans.

Response

Restore the expected mount or directory from the deployment and backup procedure; do not create an arbitrary empty path over an unknown tablespace location. CREATE TABLESPACE is guarded by PreventInTransactionBlock, so it cannot run inside an explicit client transaction block; there is no explicit block to roll back for that command itself. If a different file consumer reports a client ERROR inside an explicit transaction, issue ROLLBACK or use an already-established savepoint before continuing. When the message comes from WAL recovery, there is no client transaction to resume: restore the path and follow the server’s restart/recovery procedure. Retry only after ownership, permissions, and the target’s contents have been checked.

Versions

The locked catalogue records this condition from 7.4; fixed source coverage is PostgreSQL 18.6. The cited source is a source-only review; no tablespace fault was induced.

58P02, 58P03, 58030

Sources

src/backend/commands/tablespace.c#L347-L359

src/backend/commands/tablespace.c#L565-L625

src/backend/commands/tablespace.c#L1515-L1525

src/backend/tcop/utility.c#L713-L717

The structured evidence record records conditional hints, dynamic errno paths, and the source/runtime boundary.