# 3D000 — 目录名称无效（invalid_catalog_name）

> PostgreSQL SQLSTATE 3D000（目录名称无效，invalid_catalog_name）的源码证据、诊断与处理参考。
---

# 3D000 — 目录名称无效

## 速览 {#at-a-glance}

SQLSTATE `3D000` 是 Class `3D` 中的 **invalid_catalog_name**。`3D000` 表示数据库/目录名称无效。请求的数据库不存在时，它可以在启动完成前出现；固定的 `dbcommands.c` 路径也会在 SQL 命令解析不存在的数据库或模板时发出它。选定启动案例报告 C=`3D000`、S=`FATAL`、`database "<generated>" does not exist`；这只是其中一个阶段，不代表整个类别。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `3D000` |
| 条件名 | `invalid_catalog_name` |
| 状态 | `有效` |
| 已知存在于 | `7.4` |
| 锁定快照 | `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` |
| 宏 | `ERRCODE_INVALID_CATALOG_NAME, ERRCODE_UNDEFINED_DATABASE` |
| 别名 | `ERRCODE_UNDEFINED_DATABASE` |

<!-- source facts: data/errcodes/3D000.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

此码覆盖不止一个阶段的数据库/目录解析。请求数据库不存在时，`postinit.c` 在启动阶段发出选定的 FATAL；`dbcommands.c` 则在 SQL 命令解析不存在的数据库或模板时使用同一条件。因此启动记录只是一个具体 producer，不是所有 3D000 的统一描述。

要把阶段作为诊断的一部分。缺失数据库的启动 DSN 产生服务器 `FATAL`，没有会话级事务；已建立的管理会话执行数据库/模板查找命令时可能产生 `ERROR`，此时适用普通回滚或保存点恢复。代码本身不能告诉你失败发生在哪个阶段。

### 阶段指引 {#scenarios}

| 阶段 | 固定 producer | 恢复边界 |
| --- | --- | --- |
| 启动选择数据库 | `postinit.c` 以 `FATAL` 报告 `database "%s" does not exist`。 | 从控制数据库修正 DSN 或创建/重命名数据库，再建立新连接；没有可回滚的会话。 |
| SQL 命令或模板查找 | `dbcommands.c` 在处理管理命令时使用 `3D000`。 | 检查命令和事务；显式事务中的 `ERROR` 需要先 `ROLLBACK` 或回到有意建立的保存点。 |

## 诊断 {#diagnosis}

检查数据库名、数据库是否被重命名或删除、发生错误的命令阶段，以及可用的控制数据库。选定的 `collector` 是原始服务器 ErrorResponse 记录，不是 csvlog/jsonlog；原始启动尝试与 psycopg 尝试彼此独立。选定运行使用相互独立的启动尝试：psycopg 的驱动 SQLSTATE 为 `null` 且没有事务，服务器原始 ErrorResponse 与新鲜的已知数据库探针共同确认服务器码和恢复路径。不要把数据库不存在与 3F000 的 schema 解析混淆。

对于启动失败，检查客户端默认值、URL 解码和环境变量展开后的准确数据库参数，再查看原始服务器 `C`、`S`、`M` 字段。对于已建立会话中的 SQL 命令，另行记录命令文本和事务状态。成功的控制数据库探针只证明可以建立新会话，不证明缺失数据库的原始尝试拥有事务。

## 处理 {#response}

使用现有控制数据库检查或创建目标数据库，或修正 DSN/命令目标后重新建立连接。会话启动前没有 `ROLLBACK` 可执行；SQL 命令路径应在所属管理事务中修复，并重新核对目标目录。

如果数据库是有意删除的，应修正应用目标或迁移，而不是重复同一启动请求。如果管理命令是在已有会话中失败，先恢复该事务，再执行目录修改。重复其他连接发送的工作前先对账；启动失败本身没有在缺失数据库中执行 SQL。

## 实测诊断 {#messages}

选定的启动分支以 `FATAL` 发出主报文 `database "%s" does not exist`，数据库名是动态值。固定的 SQL 命令路径使用同一 SQLSTATE，但外围操作和事务边界可能不同。只有客户端启动异常而没有服务器 ErrorResponse，证据不足。

选定名称 `c3d000_missing_cff0e8d38be4` 是本次运行生成的值。服务器 ErrorResponse 为 `C=3D000`、`S=FATAL`；psycopg 启动的 `sqlstate=null` 与已知数据库探针属于独立尝试，不是同一会话的其他视图。

## 代表案例 {#case}

<!-- BEGIN SQLSTATE SNIPPET: invalid_database -->

注册表包含服务器启动 ErrorResponse 后执行的探针。触发点是在新启动连接上使用随机数据库名，失败发生在会话建立前，不能用 SQL 语句重现。

```sql
SELECT 1;
```

<!-- END SQLSTATE SNIPPET -->

18.6 服务器 ErrorResponse 为 C=`3D000`、S=`FATAL`、`database "c3d000_missing_cff0e8d38be4" does not exist`。驱动启动诊断的 SQLSTATE 为 `null`，失败连接没有事务；已知可用连接探针返回 `1`，状态 `IDLE`。

可下载的案例与证据投影分别是 [`3D000 案例 JSON`](../../data/cases/3d000.json) 和 [`作者证据`](../../data/evidence/3d000.json)。运行器清单为 `verify/cases/3D000/cases.json`；发布前会将页面 SQL 与共享注册表比对。

## 版本 {#versions}

上面的生成事实表记录锁定的目录快照和最早观察到的定义。本页自然运行范围是 PostgreSQL 18.6 与 10.21，不能据此推断所有中间版本的行为。

## 相关 {#related}

- [`3F000` — invalid_schema_name](../3f000/)
- [`28000` — invalid_authorization_specification](../28000/)

## 来源 {#sources}

- `src.postinit-missing-db.18.6` — `src/backend/utils/init/postinit.c` at `REL_18_6` commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`; fixed blob SHA-256 `abcf80637b153d3aa6f0d2b600943af0a2b4d9a393d05a844db91f8b6b66d0d7` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/init/postinit.c#L1014-L1017)).
- `src.postinit-missing-db.10.23` — `src/backend/utils/init/postinit.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `be912628b29f34afc7b7fbc9d2f480c5ac9cb6ce013a1d992fc7415a311a95ed` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/utils/init/postinit.c#L846-L848)).
- `src.dbcommands-missing-database.18.6` — `src/backend/commands/dbcommands.c` at `REL_18_6` commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`; fixed blob SHA-256 `64b77d2197dce16eb1ad19d8168382459d621a03df0b00be157f7db39ca22acf` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/dbcommands.c#L1702-L1704)).
- `src.dbcommands-missing-database.10.23` — `src/backend/commands/dbcommands.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `cf9e069415deb7d50ef931048616ae7f9a459d6db64e3d54a0062e8334970ce6` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/commands/dbcommands.c#L806-L808)).
- `src.calls.REL_18_6` / `src.calls.REL_10_23` — fixed local call scans, SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf` / `00d16d3eb01b71ccf1b245c8f3102f9d0ec9f36fb02777b8dd1b99fcb263040c`; these scans preserve the resolved call context used by the claims.
