Errore di caricamento backup a causa di TransferManager non inizializzato

Dopo l’aggiornamento a v2026.8.0-latest.1 +4, i miei backup hanno iniziato a fallire. Ecco i log: log.txt.zip (22,1 KB)

In particolare, questa è la sezione che sembra rilevante:

[2026-08-04 03:37:52] Uploading archive...
[2026-08-04 03:37:52] EXCEPTION: uninitialized constant Aws::S3::TransferManager
[2026-08-04 03:37:52] /var/www/discourse/lib/s3_helper.rb:453:in 'S3Helper#transfer_manager'
/var/www/discourse/lib/s3_helper.rb:332:in 'S3Helper#upload_file'
/var/www/discourse/lib/backup_restore/s3_backup_store.rb:48:in 'BackupRestore::S3BackupStore#upload_file'
/var/www/discourse/lib/backup_restore/creator.rb:437:in 'BackupRestore::Creator#upload_archive'
/var/www/discourse/lib/backup_restore/creator.rb:41:in 'BackupRestore::Creator#run'
/var/www/discourse/lib/backup_restore.rb:13:in 'BackupRestore.backup!'
/var/www/discourse/app/jobs/regular/create_backup.rb:10:in 'Jobs::CreateBackup#execute'
/var/www/discourse/app/jobs/base.rb:313:in 'block (2 levels) in Jobs::Base#perform'

Non sono sicuro di come risolvere questo problema.

Ho aggiornato a v2026.9.0-latest +565, ma ho ancora riscontrato esattamente lo stesso problema.

La versione di Discourse che stai utilizzando include una versione di aws-sdk-s3 che dovrebbe fornire Aws::S3::TransferManager.

Stai utilizzando l’installazione Docker ufficiale di Discourse? Se stai usando la configurazione Docker ufficiale, il contenitore è stato completamente ricostruito come parte dell’aggiornamento?

Sì, credo di utilizzare l’installazione Docker ufficiale di Discourse. C’è un modo per esserne sicuro? È passato un po’ di tempo dall’installazione.

Per aggiornare, ho eseguito ./launcher rebuild app. Presumo che questo significhi che il container è stato completamente ricostruito, ma potrei sbagliarmi?

Alcuni dettagli aggiuntivi che potrebbero essere rilevanti:

  • In esecuzione Ubuntu 24.04.4 LTS
  • app.yml installa i plugin ufficiali docker_manager e discourse-doc-categories nell’hook after_code. Non ci sono altri plugin definiti in app.yml.
  • Sto cercando di archiviare i backup in un archiviazione compatibile con S3 fornita da Backblaze, e questo funzionava in precedenza.

Un elemento che potrebbe aiutare a restringere il campo è verificare quale gem aws-sdk-s3 viene effettivamente caricata all’interno del container in esecuzione.

La modifica a Discourse che ha introdotto Aws::S3::TransferManager ha anche aggiornato aws-sdk-s3 da 1.182.0 a 1.227.0:

Nella revisione di Discourse che hai linkato, Gemfile.lock dovrebbe ancora utilizzare aws-sdk-s3 1.227.0, che fornisce Aws::S3::TransferManager.

Potresti provare a entrare nel container:

cd /var/discourse
./launcher enter app

Poi, all’interno del container:

cd /var/www/discourse
bundle info aws-sdk-s3
bundle exec ruby -e '
require "aws-sdk-s3"
puts "gem: #{Gem.loaded_specs["aws-sdk-s3"]&.full_name}"
puts "path: #{Gem.loaded_specs["aws-sdk-s3"]&.full_gem_path}"
p Aws::S3.autoload?(:TransferManager)
p Aws::S3::TransferManager
'

Potrebbe essere utile anche controllare l’applicazione stessa sotto Rails:

RAILS_ENV=production bundle exec rails runner '
puts "aws-sdk-s3: #{Gem.loaded_specs["aws-sdk-s3"]&.version}"
p Aws::S3.autoload?(:TransferManager)
p Aws::S3::TransferManager
'

Poi esci dal container con:

logout

Se ciò riporta una versione più vecchia di aws-sdk-s3, oppure se TransferManager non è presente,
questo spiegherebbe l’eccezione del backup e suggerirebbe che le gem installate nel container non corrispondono all’attuale
Gemfile.lock di Discourse.

Se riporta 1.227.0 e risolve correttamente
Aws::S3::TransferManager, allora il problema è più insolito e sapremo di dover esaminare cosa differisce tra il processo di backup di Sidekiq e quell’ambiente interattivo.

Dato che stai usando ./launcher rebuild app, sembra proprio che tu stia seguendo il flusso di lavoro standard di discourse_docker; i comandi sopra ci diranno più precisamente cosa è effettivamente finito nel container ricostruito.

Sembra che io abbia una vecchia versione di aws-sdk-s3.

$ bundle info aws-sdk-s3
  * aws-sdk-s3 (1.177.0)
	Summary: AWS SDK for Ruby - Amazon S3
	Homepage: https://github.com/aws/aws-sdk-ruby
	Source Code: https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sdk-s3
	Changelog: https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sdk-s3/CHANGELOG.md
	Path: /var/www/discourse/vendor/bundle/ruby/3.4.0/gems/aws-sdk-s3-1.177.0

Mentre indagavo su questo, mi è venuto in mente di aver usato questa soluzione temporanea per aggirare un problema con l’AWS SDK che non funzionava con Backblaze. Aggiornandomi sull’argomento, sembra che Backblaze abbia aggiornato la propria API, il che rende la soluzione temporanea non necessaria.

Dopo aver rimosso la soluzione temporanea, il backup ha avuto esito positivo! Grazie per l’aiuto. :heart:

Un pensiero in merito: i modelli di compatibilità temporanei come questo potrebbero essere più sicuri se dotati di una sorta di condizione di auto-scadenza o di protezione, anziché continuare a sovrascrivere le dipendenze di Discourse all’infinito.

Ad esempio, per i backport temporanei del codice sorgente, ho in programma di utilizzare hook in produzione che prima controllino se la correzione upstream è già presente e applichino la patch solo se è ancora necessaria.

In questo caso, qualcosa di simile avrebbe potuto potenzialmente impedire che il pin di aws-sdk-s3 1.177.0 rimanesse attivo una volta che Discourse stesso ha iniziato a dipendere da funzionalità più recenti dell’SDK:

hooks:
  after_bundle_exec:
    - exec:
        cd: $home
        cmd:
          - |
            if grep -q "Aws::S3::TransferManager" lib/s3_helper.rb; then
              echo "Discourse ora richiede Aws::S3::TransferManager; salto il downgrade obsoleto di Backblaze aws-sdk-s3"
            else
              echo "Applico il pin temporaneo di compatibilità Backblaze aws-sdk-s3"
              bundle config set frozen false
              sed -i 's/gem "aws-sdk-s3", require: false/gem "aws-sdk-s3", "1.177.0", require: false/' Gemfile
              bundle update aws-sdk-s3
              bundle add aws-sdk-core --version 3.215
            fi

Quel controllo specifico è solo esemplificativo: una verifica di versione più generale o un errore esplicito quando Discourse supera la versione SDK prevista sarebbero probabilmente preferibili.

Anche un errore esplicito sarebbe probabilmente preferibile rispetto alla generazione silenziosa di un container i cui gem non corrispondono più alle versioni attese da Discourse.

Sebbene concordassi che sarebbe stato preferibile un errore esplicito, il fatto era che volevo che i gem non corrispondessero alle versioni richieste da Discourse, poiché la versione più recente di aws-sdk-s3 inviava intestazioni non supportate da Backblaze e desideravo che i backup funzionassero.

Non so se esistesse un controllo che avrei potuto impostare preventivamente per ricevere una notifica quando la soluzione temporanea non fosse più necessaria. Ho implementato la soluzione temporanea un anno e mezzo fa, ad aprile 2025, prima che fosse disponibile una correzione.

Penso che la cosa migliore che avrei potuto fare fosse aggiungere una data di scadenza, per costringermi a verificare se la soluzione temporanea fosse ancora necessaria. Una funzionalità del genere potrebbe essere utile. Oppure, forse, la responsabilità ricade su di me per essere più proattivo e impostare promemoria per verificare se la soluzione temporanea sia ancora necessaria. Avere alcune note mi è stato utile in questo senso.