Discourse AI: la richiesta Gemini bloccata tramite promptFeedback.blockReason viene trattata come risposta vuota e non viene mai tradotta

Descrizione

Quando l’API Gemini di Google rifiuta una richiesta con promptFeedback.blockReason, Discourse AI gestisce la risposta come una replica di successo ma vuota. Nella traduzione AI, questo ha due effetti: l’argomento o il post non riceve mai una lingua rilevata, quindi non viene mai tradotto, e il backfill invia nuovamente la stessa richiesta bloccata nelle esecuzioni successive. Nessun elemento indica a un amministratore che si è verificato un blocco.

Osservato su un sito self-hosted in esecuzione con release/2026.7 (2026.7.3, commit f1caa6321287f918644fba9ff8943579fdcf027a) con il plugin discourse-ai incluso. La richiesta era il rilevamento della lingua di un titolo di argomento, utilizzando l’agente rilevatore di lingua locale integrato su gemini-3.5-flash-lite. Il titolo era una frase breve e innocua in svedese. Lo stesso titolo è stato tradotto da gemini-3.8-flash senza blocchi.

Google ha risposto con HTTP 200 e un singolo evento di stream senza candidati:

data: {"promptFeedback": {"blockReason": "PROHIBITED_CONTENT"},"usageMetadata": {"promptTokenCount": 417,"totalTokenCount": 417,"promptTokensDetails": [{"modality": "TEXT","tokenCount": 417}],"serviceTier": "standard"},"modelVersion": "gemini-3.5-flash-lite","responseId": "..."}

La richiesta include già BLOCK_NONE per le quattro categorie di sicurezza impostate da Discourse AI, quindi questo blocco non è influenzato da quelle impostazioni. Il registro di audit registra response_status 200.

Causa principale

  1. DiscourseAi::Completions::Endpoints::Gemini#decode_chunk legge solo candidates da ciascun evento di stream. promptFeedback non viene mai ispezionato, quindi una richiesta bloccata produce un risultato vuoto senza errori.
  2. DiscourseAi::Translation::LanguageDetector#detect restituisce nil quando la risposta non corrisponde al suo modello di tag linguistico, il che è il caso di una risposta vuota. L’argomento o il post mantiene locale NULL.
  3. Jobs::TopicsLocaleDetectionBackfill seleziona argomenti con locale NULL in ogni esecuzione e non ha un limite di tentativi, quindi leggendo il codice, la richiesta bloccata viene ripetuta ogni cinque minuti per tutta la durata in cui l’argomento è nella finestra di backfill. I post sono limitati a due tentativi di rilevamento al giorno dalla quota di rilocazione e vengono ritentati ogni giorno.
  4. I candidati per la traduzione richiedono un locale rilevato, quindi l’elemento non viene mai tradotto.

Lo stesso codice è presente su main al 2026-10-03.

Correzione suggerita

  1. Rilevare promptFeedback.blockReason nell’endpoint Gemini e sollevare o registrare un errore distinto e visibile che specifichi la ragione.
  2. Registrare il fallimento sull’argomento o sul post in modo che il backfill smetta di ripetere una richiesta che verrà nuovamente bloccata, oppure applicare un limite di tentativi al rilevamento degli argomenti come già esiste per i post.
  3. Mostrare gli elementi bloccati nella pagina di amministrazione della traduzione, in modo che un amministratore possa impostare la lingua manualmente.

Riproduzione

Il blocco dipende dal filtro di Google e non può essere forzato con un input noto. Le chiamate interessate possono essere trovate nel registro di audit:

SELECT id, created_at, language_model, post_id, topic_id, response_status
FROM ai_api_audit_logs
WHERE feature_name = 'translation'
  AND raw_response_payload LIKE '%blockReason%'
ORDER BY created_at

Soluzione temporanea

Impostare manualmente la lingua dell’argomento consente di procedere con la traduzione. Su questo sito, il modello di traduzione non ha bloccato lo stesso testo.

1 Mi Piace

grazie per la segnalazione @Sailor :+1:

verrà risolto con FIX: Handle Gemini errors and blocked prompts reported in successful responses - Pull Request #44262 - discourse/discourse - GitHub

1 Mi Piace

Grazie per la rapida correzione. Una parte di questa segnalazione rimane aperta dopo #44262, almeno stando alla differenza (diff).

Con la modifica, un rilevamento bloccato viene registrato e, per gli argomenti, è limitato a due tentativi al giorno. L’elemento in questione resta comunque senza locale, quindi non viene mai tradotto e continua a essere conteggiato come in attesa di rilevamento all’infinito. Nessun elemento nell’interfaccia di amministrazione mostra quali siano questi elementi.

Durante un unico backfill di circa 6.700 post e i relativi argomenti su questo sito, si sono verificati tre casi, tutti con gemini-3.5-flash-lite e PROHIBITED_CONTENT, e tutti innocui: un titolo di argomento, un post di una sola frase e un post composto da un singolo link.

Due possibili rimedi:

  1. Un locale di riserva quando il rilevamento è bloccato, ad esempio il locale dell’interfaccia dell’autore o, per una risposta, il locale del suo argomento. Nel caso specifico in cui il locale è stato impostato manualmente e l’elemento è stato lasciato al backfill, il modello di traduzione lo ha tradotto senza obiezioni.
  2. In caso contrario, un elenco o un conteggio degli elementi il cui rilevamento è stato bloccato nella pagina di amministrazione della traduzione, in modo da poter impostare manualmente il locale.