PostgreSQL · 错误码速查
PostgreSQL「role does not exist」:服务器上没有这个用户名,先确认连的是哪台库、用的是哪个名字
这条报错说明你要登录的数据库用户名在这台服务器上不存在。最常见的三种情况:psql 没写 -U,默认拿操作系统用户名(如 ubuntu)去登录;Docker 容器复用了旧数据卷,POSTGRES_USER 没生效;建用户时没加双引号,MyUser 实际被建成了 myuser。先用 sudo -u postgres psql -c '\du' 看现有用户,再用 CREATE ROLE ... LOGIN 补建,或把连接串里的用户名改对。
官方原文
role "%s" does not exist出自 PostgreSQL 源码 miscinit.c 的 InitializeSessionUserId(),以 FATAL 级别报出,错误码 ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION(SQLSTATE 28000)。客户端看到的完整形式一般是 psql: error: connection to server on socket "..." failed: FATAL: role "ubuntu" does not exist。
出处:PostgreSQL 源码 REL_18_STABLE:src/backend/utils/init/miscinit.c(InitializeSessionUserId) 最后核对:
| SQLSTATE | 28000(invalid_authorization_specification) | 出处 |
|---|---|---|
| 报错时机 | 通过 pg_hba.conf 认证之后、建立会话时查 pg_authid 找不到该名字 | 出处 |
| 密码认证时 | 客户端只看到 password authentication failed;服务器日志 DETAIL 写 Role "xxx" does not exist. | 出处 |
| psql 默认用户名 | 操作系统用户名;默认数据库名 = 用户名 | 出处 |
| Docker 镜像 | POSTGRES_USER 只在数据目录为空、首次初始化时创建 | 出处 |
先弄清楚:服务器收到的到底是哪个用户名
报错里引号中的名字就是服务器收到的用户名,它往往不是你以为的那个。客户端没有显式指定用户名时,会按下面的顺序取值:
| 来源 | 例子 | 常见坑 |
|---|---|---|
命令行 -U 或连接串里的 user | psql -U app、postgresql://app@host/db | 连接串写错、环境变量覆盖 |
环境变量 PGUSER | export PGUSER=app | CI、容器里残留的旧变量 |
| 都没写时:操作系统用户名 | Linux 用户 ubuntu 执行 psql → 以 ubuntu 登录 | 新装的库里只有 postgres 一个用户 |
所以新装完 PostgreSQL 直接敲 psql,几乎必然得到 role "你的系统用户名" does not exist。这不是安装失败,而是库里只有 postgres 这个超级用户。
如果 pg_hba.conf 用的是密码认证(scram-sha-256 / md5),用户名不存在时服务器故意只回 password authentication failed,避免向客户端泄露“这个用户不存在”。这时要看服务器日志里的 DETAIL: Role "xxx" does not exist.,见 password authentication failed。
Docker:改了 POSTGRES_USER 还是报错,多半是数据卷没清
官方 postgres 镜像文档写明:POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB 这些变量只在数据目录为空时生效,已有数据的卷启动时原样保留。典型过程是:第一次用默认配置起过容器(只建了 postgres),后来在 compose 里加上 POSTGRES_USER=app,重建容器但沿用了同一个卷,app 从来没被创建。
# 1) 看容器里实际有哪些用户(镜像内 Unix 套接字是 trust,可以直接进)
docker exec -it <容器名> psql -U postgres -c '\du'
# 2) 看数据卷是不是旧的
docker volume ls
docker inspect <容器名> --format '{{ json .Mounts }}'- 数据不重要(本地开发):
docker compose down -v删除卷后重新up,变量会在首次初始化时生效。这会删掉卷里的全部数据。 - 数据要保留:不要删卷,进容器用
CREATE ROLE app LOGIN PASSWORD '...'手动补建,并按需GRANT。 - 另一种常见情况:宿主机自己也装了 PostgreSQL 并占着 5432,你的客户端连的是宿主机上的库,不是容器。用
ss -ltnp | grep 5432或换个映射端口(如5433:5432)确认。
大小写:建的是 myuser,登录用的是 MyUser
SQL 里没加双引号的标识符会被折成小写,而客户端发来的用户名是原样比对的。两边对不上就会报 role does not exist:
| 建用户的语句 | 库里实际的名字 | psql -U MyUser 结果 |
|---|---|---|
CREATE ROLE MyUser LOGIN; | myuser | 失败:role "MyUser" does not exist |
CREATE ROLE "MyUser" LOGIN; | MyUser | 成功 |
CREATE ROLE myuser LOGIN; | myuser | 用 -U myuser 成功 |
建议用户名一律用小写字母、数字和下划线,避免以后每条 SQL 都要加引号。
补建用户:最小权限写法
-- 以超级用户连接(如 sudo -u postgres psql)后执行
SELECT rolname, rolcanlogin, rolsuper FROM pg_roles ORDER BY rolname; -- 只读:先看现有用户
CREATE ROLE app LOGIN PASSWORD '换成强密码';
CREATE DATABASE appdb OWNER app; -- 需要独立库时
-- 或者只给已有库的权限:
GRANT CONNECT ON DATABASE appdb TO app;- 想用和系统用户同名的账号免密登录本机:
sudo -u postgres createuser --interactive ubuntu,再createdb -O ubuntu ubuntu,之后直接psql即可(走 peer 认证)。 - 用户存在但报
role "xxx" is not permitted to log in:说明建成了 NOLOGIN(CREATE ROLE默认就是 NOLOGIN),执行ALTER ROLE xxx LOGIN;。 - 用户刚建好仍报错:确认连的是同一个实例(端口、容器、主机),
SELECT inet_server_addr(), inet_server_port();可以核对。
常见问题
psql: FATAL: role "ubuntu" does not exist 怎么解决?
psql 没指定 -U 时用操作系统用户名登录,新装的库里只有 postgres 用户。用 sudo -u postgres psql 进去,或者 sudo -u postgres createuser --interactive ubuntu 建一个同名用户。
Docker 里设置了 POSTGRES_USER 为什么还是 role does not exist?
POSTGRES_USER 只在数据目录为空、首次初始化时生效。沿用旧数据卷时不会创建新用户。开发环境可以删卷重建(会丢数据),要保留数据就进容器手动 CREATE ROLE。
明明建了用户,为什么还提示不存在?
多半是大小写:CREATE ROLE MyUser 实际建的是 myuser。要么登录时用小写,要么建用户时给名字加双引号。也要确认连的是同一个实例。
为什么有时报 password authentication failed 而不是 role does not exist?
pg_hba.conf 用密码认证时,用户不存在也只返回密码认证失败,避免泄露用户是否存在。服务器日志里会有 DETAIL: Role "xxx" does not exist.。
role 和 user 有什么区别?
在 PostgreSQL 里是同一种对象。CREATE USER 等于 CREATE ROLE 加 LOGIN 属性;没有 LOGIN 的 role 只能用来分组授权,不能登录。
免费 · 留邮箱领检查单
PostgreSQL 14 停更升级检查单(Excel 可直接打开)
- PG14 2026-11-12 停更,升 17 / 18 前后 19 项检查:只读预检、--check、回滚、补统计、回归
- 每项写清怎么查、通过标准、不处理会怎样(附测试库实测数字)
- 配合站上的只读预检 SQL 使用,每个业务库各跑一次
下一步
价格以对应页面当前标价为准。
出处(最后核对 2026-11-05)
- PostgreSQL 源码 REL_18_STABLE:src/backend/utils/init/miscinit.c(InitializeSessionUserId)
- PostgreSQL 源码 REL_18_STABLE:src/backend/libpq/crypt.c(get_role_password)
- PostgreSQL 18 文档:psql(默认用户名与默认数据库名)
- Docker 官方 postgres 镜像文档(POSTGRES_USER / POSTGRES_DB,仅空数据目录初始化时生效)
- PostgreSQL 18 文档 4.1.1:Identifiers and Key Words(未加引号的标识符折叠为小写)
- PostgreSQL 18 文档:CREATE ROLE
本页摘录并解读上面列出的官方文档,不是官方页面;官方文档更新后以官方为准。本页内容都来自官方文档,没有我们自己的测试结果。