# 0P000 — 角色规范无效（invalid_role_specification）

> PostgreSQL SQLSTATE 0P000（角色规范无效，invalid_role_specification）的源码证据、诊断与处理参考。
---

# 0P000 — 角色规范无效

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

SQLSTATE `0P000` 是 Class `0P` 中的 **invalid_role_specification**。在 `ENABLE_SSPI` 下，固定的 Windows SSPI 路径在把 SAM 账户名转换为 UPN 时以服务器 `LOG` 分支使用它；它不是普通的“角色不存在”登录结果，也不是客户端 ErrorResponse。

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

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `0P000` |
| 条件名 | `invalid_role_specification` |
| 状态 | `有效` |
| 已知存在于 | `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_ROLE_SPECIFICATION` |
| 别名 | `—` |

<!-- source facts: data/errcodes/0P000.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

`0P000` 是 `invalid_role_specification`。固定的 `pg_SSPI_make_upn` 路径构造 `DOMAIN\user`，调用 Windows `TranslateName` 得到 `user@realm`；转换失败、结果没有 `@`，或 realm/账户无法放入目标缓冲区时记录 `0P000`。这些是 `ENABLE_SSPI` 下的服务器 `LOG` 分支，不是客户端 ErrorResponse，也不是普通角色缺失结果。

## 诊断 {#diagnosis}

确认失败路径确实是 Windows SSPI，并结合服务器日志检查 SAM 账户/域名及配置的 realm 或 UPN 映射。`TranslateName` 失败（包括结果不含 `@`）记录 `could not translate name`；realm 过长记录 `realm name too long`；转换后的账户过长记录 `translated account name too long`。使用 trust 认证的临时实例无法忠实演示这一外部身份边界；启动 ErrorResponse 也可能是 28000 或 28P01。

## 处理 {#response}

修复 SSPI 账户/realm 映射或 Windows 名称转换配置后建立新连接。应把这些服务器日志诊断与启动认证响应、SQL 角色不存在和密码失败分开。

## 报文 {#messages}

固定 SSPI 源码以 `LOG` 和 SQLSTATE `0P000` 记录以下主报文模板：`could not translate name`、`realm name too long`、`translated account name too long`。这些是服务器日志记录；只有客户端异常或没有匹配服务器日志的启动 ErrorResponse，都不能证明 `0P000`。

## 代表案例 {#case}

本页没有选定的自然 SQL 运行。结构化证据记录的是源码或定义边界；客户端 `RAISE` 不能代表服务器机制。

## 版本 {#versions}

上面的生成事实表记录锁定的目录快照和最早观察到的定义。本页没有选定的自然 SQL 运行；固定 REL_18_6/REL_10_23 的 SSPI 源码比较不能当作实测结果，也不能据此推断所有中间版本的行为。

## 相关 {#related}

- [`28000` — invalid_authorization_specification](../28000/)
- [`28P01` — 相关条件](../28p01/)

## 来源 {#sources}

- `src.auth-name-translation.18.6` — `src/backend/libpq/auth.c` at `REL_18_6` commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`; fixed blob SHA-256 `94252cb1e2c49b0ddb15f6596d0abf8056c84493de07cc81439da4c5b07018f1` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/libpq/auth.c#L1514-L1516)).
- `src.auth-name-translation.10.23` — `src/backend/libpq/auth.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `15418faa6d6ee1b2a4ad1e50ebc9b34c2daf4799f7062df425e33dbf777ade61` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/libpq/auth.c#L1699-L1701)).
- `src.auth-sspi-upn.10.23` — `src/backend/libpq/auth.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `15418faa6d6ee1b2a4ad1e50ebc9b34c2daf4799f7062df425e33dbf777ade61` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/libpq/auth.c#L1666-L1758)).
- `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.
