PG::UndefinedTable: ERROR: a relação "voice_rooms" não existe

Continuando a discussão de Fatal: could not read Username for 'https://github.com':

Acredito que os problemas do GitHub já estejam resolvidos, mas a atualização falha. Este é o primeiro incidente:

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

Uso um setup de 2 contêineres (também executei data, sem erros) e estou na versão mais recente.

Algumas ideias?

PG::UndefinedTable: ERROR: relation "voice_rooms" does not exist aparece porque as migrações para o novo plugin voice incluído no núcleo ainda não foram executadas.

O que estava acima do rake aborted!?

Tem… bastante coisa :laughing: Mas nada que me chame a atenção.

x86_64 arch detected.                                                                                                                                                 
Ensuring launcher is up to date                                                                                                                                       
Launcher is up-to-date                                                                                                                                                
Stopping old container                                                                                                                                                
+ /usr/bin/docker stop -t 600 web_only                                                                                                                                
web_only                                                                                                                                                              
2.0.20260812-0036: Pulling from discourse/base                                                                                                                        
Digest: sha256:837e8ed4b5916baa36856b842ad84fe262b6b1b5550701f8844b13cc7acad7a5                                                                                       
Status: Image is up to date for 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 -- : Reading from stdin                                                                                                      
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 configu
red!"; 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 sp
eccified"

Suspeito que isso possa estar relacionado às versões de migração do plugin resenha anterior coincidirem com as do novo plugin voice — provavelmente porque você o instalou antes? Se não tiver certeza, pode tentar executar isso no seu psql:

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

Veja resenha/db/migrate/20241107000000_create_resenha_rooms.rb at b87ca4e20d649ba6b7bdc4615b289c414854889e · xfalcox/resenha · GitHub e discourse/plugins/voice/db/migrate/20241107000000_create_voice_rooms.rb at main · discourse/discourse · GitHub

Deveria haver uma correção no núcleo para essas versões de migração conflitantes… Imagino que isso deve afetar outras pessoas também. Fiquem atentos.

É, eu tentei no início, mas depois removi.

Ok - provavelmente é uma migração do Resenha que deveria ter sido executada, mas não foi. Como o mesmo número de versão da migração é usado no core para voice, tentar adicionar uma coluna para voice_rooms de repente não funcionará, pois o nome da tabela ainda é resenha_rooms.

Você pode executar o seguinte no seu psql por enquanto:

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
$$;

Ele faz o seguinte:

  1. verifica quais tabelas do Resenha e do Voice existem.
  2. se recusará a continuar se ambas existirem (não espero que isso aconteça)
  3. verifica se as migrações registradas são as que esperamos
  4. renomeia as tabelas existentes:
    • 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. isso ajuda com o estado intermediário estranho que você tem. a reconstrução posterior deve ter sucesso

Isso deve permitir que o restante das suas migrações do core tenha sucesso (a migração de voice mais recente do core, que faz o renomeio, será ignorada/no-op).

Vou verificar com nossa equipe se devemos commitar isso como uma tarefa rake.

Obrigado! Funcionou perfeitamente.

Eu também tive esse problema — e executar aquele script exigiu um pouco de orientação do ask.discourse.com, pois não é muito fácil para administradores de sistemas menos experientes!

Aqui está um resumo para os outros:


Para quem estiver enfrentando isso na instalação padrão com Docker, aqui está como executar o script acima de fato.

Obtenha um shell e abra o psql.

  • Contêiner único:

    cd /var/discourse
    ./launcher start app   ## Necessário apenas se você já teve uma reconstrução falha
    ./launcher enter app
    su -c 'psql discourse' postgres
    
    
  • Configuração com dois contêineres:

    cd /var/discourse
    ./launcher enter data
    su -c 'psql discourse' postgres
    
    

Você deve ver o prompt discourse=#. Se tiver dúvidas, execute \conninfo.

Execute o script.

Cole todo o bloco DO $$ ... $$; da postagem acima do nat no prompt e pressione Enter. Uma execução bem-sucedida imprime avisos como:

NOTICE:  Renamed resenha_rooms to voice_rooms
NOTICE:  Renamed resenha_room_memberships to voice_room_memberships
...

Se, em vez disso, ele levantar uma exceção (por exemplo, “Both Resenha and Voice tables exist. Nothing was changed.”), pare e cole a mensagem de volta aqui — o script é intencionalmente seguro e não altera nada nesse caso.

Saia e reconstrua.

\q
exit

e, de volta no host:

./launcher rebuild app          # contêiner único
./launcher rebuild web_only     # dois contêineres (também pode ser feito via bootstrap, é claro)

Você pode precisar de duas reconstruções — a primeira finaliza o estado de migração aplicado parcialmente, e a segunda completa o processo com sucesso.