PG::UndefinedTable: ERROR: 关系 "voice_rooms" 不存在

继续此讨论:Fatal: could not read Username for ‘https://github.com’

我认为 GitHub 的问题现在已经解决了,但升级仍然失败。这是第一个错误:

rake aborted!
StandardError: An error has occurred, this and all later migrations canceled: (StandardError) 
PG::UndefinedTable: ERROR:  relation "voice_rooms" does not exist

我使用的是双容器配置(我也执行了 data,没有报错),并且已经升级到最新版本。

有什么建议吗?

出现 PG::UndefinedTable: ERROR: relation "voice_rooms" does not exist 错误,是因为新核心捆绑的 voice 插件的迁移尚未运行。

rake aborted! 之前显示的是什么?

嗯……内容有点多 :laughing: 但没有什么能引起我兴趣的。

检测到 x86_64 架构。
正在确保启动器为最新版本
启动器已是最新版本
正在停止旧容器
+ /usr/bin/docker stop -t 600 web_only
web_only
2.0.20260812-0036: 从 discourse/base 拉取
摘要: sha256:837e8ed4b5916baa36856b842ad84fe262b6b1b5550701f8844b13cc7acad7a5
状态: discourse/base:2.0.20260812-0036 镜像已是最新
docker.io/discourse/base:2.0.20260812-0036
/usr/local/lib/ruby/gems/3.4.0/gems/pups-1.4.0/lib/pups.rb
/usr/local/bin/pups --stdin
I, [2026-09-03T08:55:23.418621 #1]  INFO -- : 正在从标准输入读取
I, [2026-09-03T08:55:23.453117 #1]  INFO -- : > thpoff echo "thpoff is installed!"
thpoff is installed!
I, [2026-09-03T08:55:23.461963 #1]  INFO -- : > /usr/local/bin/ruby -e 'if (ENV["DISCOURSE_SMTP_ADDRESS"] == "smtp.example.com" && ENV["DISCOURSE_SKIP_EMAIL_SETUP"] != "1"); puts "Aborting! Mail is not configured!"; exit 1; end'
I, [2026-09-03T08:55:23.608522 #1]  INFO -- : > /usr/local/bin/ruby -e 'if ENV["DISCOURSE_HOSTNAME"] == "discourse.example.com"; puts "Aborting! Domain is not configured!"; exit 1; end'
I, [2026-09-03T08:55:23.743204 #1]  INFO -- : > /usr/local/bin/ruby -e 'if (ENV["DISCOURSE_CDN_URL"] || "")[0..1] == "//"; puts "Aborting! CDN must have a protocol specified"

我怀疑这可能与之前的 resenha 插件的迁移版本与新的 voice 插件的迁移版本相同有关——大概是因为你之前先安装了它?如果你不确定的话,能否尝试在你的 psql 中运行以下命令:

  SELECT version, name, direction, created_at, git_version
  FROM schema_migration_details
  WHERE version = '20241107000000'
  ORDER BY created_at;

请参见 resenha/db/migrate/20241107000000_create_resenha_rooms.rb at b87ca4e20d649ba6b7bdc4615b289c414854889e · xfalcox/resenha · GitHubdiscourse/plugins/voice/db/migrate/20241107000000_create_voice_rooms.rb at main · discourse/discourse · GitHub

核心代码应该会有一个针对这种迁移版本冲突的修复。我想这应该也会影响其他人。请留意后续更新。

对,我一开始试过,但后来把它删掉了。

好的——这很可能是一次被假定已经运行但实际上并未运行的 Resenha 迁移。由于核心代码中语音功能使用了相同的迁移版本号,此时尝试为 voice_rooms 添加列会失败,因为表名仍然是 resenha_rooms

你可以暂时在 psql 中运行以下代码:

DO
$$
  DECLARE
    has_resenha boolean;
    has_voice   boolean;
    table_pair  record;
  BEGIN
    SELECT EXISTS (SELECT 1
                   FROM unnest(ARRAY [
                     'resenha_rooms',
                     'resenha_room_memberships',
                     'resenha_sessions',
                     'resenha_co_presences',
                     'resenha_recordings',
                     'resenha_invites'
                     ]) AS names(name)
                   WHERE to_regclass(format('public.%I', name)) IS NOT NULL)
    INTO has_resenha;

    SELECT EXISTS (SELECT 1
                   FROM unnest(ARRAY [
                     'voice_rooms',
                     'voice_room_memberships',
                     'voice_sessions',
                     'voice_co_presences',
                     'voice_recordings',
                     'voice_invites'
                     ]) AS names(name)
                   WHERE to_regclass(format('public.%I', name)) IS NOT NULL)
    INTO has_voice;

    IF has_resenha AND has_voice THEN
      RAISE EXCEPTION
        'Both Resenha and Voice tables exist. Nothing was changed.';
    END IF;

    IF NOT has_resenha THEN
      IF to_regclass('public.voice_rooms') IS NOT NULL THEN
        RAISE NOTICE 'The tables have already been renamed.';
        RETURN;
      END IF;

      RAISE EXCEPTION
        'Neither resenha_rooms nor voice_rooms exists. Nothing was changed.';
    END IF;

    IF EXISTS (SELECT 1
               FROM schema_migrations
               WHERE version = '20260831162602') THEN
      RAISE EXCEPTION
        'The rename migration is already recorded. Nothing was changed.';
    END IF;

    FOR table_pair IN
      SELECT *
      FROM (VALUES ('resenha_rooms', 'voice_rooms', '20241107000000'),
                   ('resenha_room_memberships', 'voice_room_memberships',
                    '20241107000000'),
                   ('resenha_sessions', 'voice_sessions', '20260305165400'),
                   ('resenha_co_presences', 'voice_co_presences',
                    '20260305165401'),
                   ('resenha_recordings', 'voice_recordings', '20260717172530'),
                   ('resenha_invites', 'voice_invites',
                    '20260813160047')) AS pairs(old_name, new_name, migration_version)
      LOOP
        IF EXISTS (SELECT 1
                   FROM schema_migrations
                   WHERE version = table_pair.migration_version) AND
           to_regclass(format('public.%I', table_pair.old_name)) IS NULL THEN
          RAISE EXCEPTION
            'Migration % is recorded, but table % is missing. Nothing was changed.',
            table_pair.migration_version,
            table_pair.old_name;
        END IF;

        IF to_regclass(format('public.%I', table_pair.old_name)) IS NOT NULL THEN
          EXECUTE format(
            'ALTER TABLE public.%I RENAME TO %I',
            table_pair.old_name,
            table_pair.new_name
                  );

          RAISE NOTICE 'Renamed % to %', table_pair.old_name, table_pair.new_name;
        END IF;
      END LOOP;
  END
$$;

它的功能如下:

  1. 检查存在哪些 Resenha 和 Voice 表。
  2. 如果两者同时存在,则拒绝继续执行(我不认为这种情况会发生)。
  3. 检查记录的迁移是否与我们预期的相符。
  4. 重命名现有的表:
    • resenha_rooms → voice_rooms
    • resenha_room_memberships → voice_room_memberships
    • resenha_sessions → voice_sessions
    • resenha_co_presences → voice_co_presences
    • resenha_recordings → voice_recordings
    • resenha_invites → voice_invites
  5. 这有助于解决你当前所处的这种奇怪的中间状态。之后的重建应该能成功。

这应该能让你的核心迁移其余部分成功执行(最近一次执行重命名的核心语音迁移将变为空操作)。

我会与我们的团队确认是否应该将此作为一个 rake 任务提交。