PG::UndefinedTable: ERROR: la relación "voice_rooms" no existe

Continuando la discusión desde Fatal: could not read Username for 'https://github.com':

Los problemas de GitHub están resueltos, creo, pero la actualización falla. Este es el primer incidente:

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

Tengo 2 contenedores (también ejecuté data, sin errores) y estoy en la última versión.

¿Ideas?

El error PG::UndefinedTable: ERROR: relation "voice_rooms" does not exist aparece porque las migraciones del nuevo plugin voice incluido en el núcleo aún no se han ejecutado.

¿Qué aparecía encima de rake aborted!?

Hay… un montón :laughing: Pero nada que me llame la atención.

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 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"

Sospecho que esto podría estar relacionado con que las versiones de migración del plugin resenha anterior coinciden con las del nuevo plugin de voz, probablemente porque lo instalaste antes. Si no estás seguro, ¿podrías intentar ejecutar esto en tu psql:

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

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

Debería haber una corrección en el núcleo para estas versiones de migración en conflicto. Imagino que también debería afectar a otros. Mantente atento.

Sí, lo probé en sus primeras etapas, pero luego lo eliminé.

Ok - probablemente se trata de una migración de Resenha que se asumió que se había ejecutado, pero no fue así. Dado que el mismo número de versión de migración se utiliza en el núcleo para voice, intentar añadir de repente una columna para voice_rooms no funcionará, porque el nombre de la tabla sigue siendo resenha_rooms.

Puedes ejecutar lo siguiente en tu psql por ahora:

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

Lo que hace es lo siguiente:

  1. Comprueba qué tablas de Resenha y Voice existen.
  2. Se negará a continuar si ambas existen (no espero que esto ocurra).
  3. Verifica que las migraciones registradas sean las que esperamos.
  4. Renombra las tablas 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. Esto ayuda con el extraño estado intermedio en el que te encuentras. La reconstrucción posterior debería tener éxito.

Debería permitir que el resto de tus migraciones del núcleo se ejecuten con éxito (hará un no-op de la migración de voice más reciente del núcleo que realiza el renombrado).

Consultaré con nuestro equipo si debemos comprometer esto como una tarea rake.

¡Gracias! Funcionó a la perfección.

Yo tuve este mismo problema y ejecutar ese script requirió un poco de orientación desde ask.discourse.com, ya que no es muy fácil para administradores de sistemas con menos experiencia.

Aquí hay un resumen para los demás:


Para quienes se encuentren con esto en la instalación estándar de Docker, así es como se ejecuta realmente el script anterior.

Obtén una shell y abre psql.

  • Contenedor único:

    cd /var/discourse
    ./launcher start app   ## Solo necesario si ya has tenido un rebuild fallido
    ./launcher enter app
    su -c 'psql discourse' postgres
    
    
  • Configuración de dos contenedores:

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

Deberías ver un prompt discourse=#. Si tienes dudas, ejecuta \conninfo.

Ejecuta el script.

Pega todo el bloque DO $$ ... $$; de la publicación de nat arriba en el prompt y presiona Enter. Una ejecución exitosa imprime avisos como:

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

Si en su lugar lanza una excepción (p. ej. «Both Resenha and Voice tables exist. Nothing was changed.»), detente y pega el mensaje de vuelta aquí — el script está diseñado para ser seguro y no cambia nada en ese caso.

Sal y reconstruye.

\q
exit

y luego, de vuelta en el host:

./launcher rebuild app          # contenedor único
./launcher rebuild web_only     # dos contenedores (también se puede hacer a través de bootstrap, por supuesto)

Puede que necesites dos reconstrucciones: la primera finaliza el estado de migración aplicado a medias y la segunda se completa limpiamente.