Aprovar um tópico na fila no nosso site auto-hospedado falhou com HTTP 500 porque o registro em fila continha payload.tags = "macos" (uma string). O valor malformado já havia sido aceito por POST /posts.
Entendo que os clientes devem enviar uma matriz de tags. O problema que estou reportando é que um escalar inválido pode ser aceito na fila de revisão e só falhar depois, quando um moderador aprova a publicação.
Versão: 2026.10.0-latest, commit 3f2bf92368c78a7fa9a755f3d046adf35dd4459b.
Evidências do incidente
A publicação exigia aprovação devido a approve_post_count.
Em 2026-10-22 13:37:52 UTC, os parâmetros da requisição Rails original já continham:
"tags" => "macos"
A requisição foi POST /posts e o log de acesso correspondente registrou HTTP 200. Os nomes dos parâmetros enviados foram title, raw, category e tags.
A leitura da revisão pendente confirmou:
{
"type": "ReviewableQueuedPost",
"status": 0,
"version": 0,
"topic_id": null,
"payload": {
"tags": "macos"
}
}
Este é um extrato dos campos relevantes, com o título, o corpo e as informações do usuário omitidos. A interface de revisão exibia a tag como cinco letras separadas: m, a, c, o, s.
Clicar em Aprovar gerou esta exceção (cinco ocorrências agrupadas nos logs):
NoMethodError (undefined method '-' for an instance of String)
lib/discourse_tagging.rb:932:in 'DiscourseTagging.tags_for_saving'
lib/discourse_tagging.rb:43:in 'DiscourseTagging.tag_topic_by_names'
lib/discourse_tagging.rb:30:in 'DiscourseTagging.tag_topic'
lib/topic_creator.rb:228:in 'TopicCreator#setup_tags'
lib/topic_creator.rb:60:in 'TopicCreator#create'
lib/post_creator.rb:519:in 'PostCreator#create_topic'
lib/post_creator.rb:209:in 'block in PostCreator#create'
lib/post_creator.rb:419:in 'block in PostCreator#transaction'
lib/post_creator.rb:419:in 'PostCreator#transaction'
lib/post_creator.rb:207:in 'PostCreator#create'
app/models/reviewable_queued_post.rb:110:in 'ReviewableQueuedPost#perform_approve_post'
app/models/reviewable.rb:433:in 'Kernel#public_send'
app/models/reviewable.rb:433:in 'block in Reviewable#perform'
app/models/reviewable.rb:431:in 'Reviewable#perform'
app/controllers/reviewables_controller.rb:287:in 'ReviewablesController#perform'
Código relevante
Estes são os caminhos de código verificados no contêiner em execução no commit acima:
- PostsController#create_params chama
params.permit(tags: %i[id name]), mas não usa os parâmetros filtrados retornados. Em seguida, atribui o valor original comresult[f] = params[f]. - NewPostManager#enqueue copia
@args[:tags]diretamente para o payload revisável. - ReviewableQueuedPost#create_options converte tags apenas quando o valor já é uma Array, deixando uma string escalar inalterada.
- DiscourseTagging.tags_for_saving então avalia
tags_arg - tag_namesquando o usuário aprovador pode criar tags, o que levanta uma exceção para uma string.
Comportamento esperado
Rejeitar um parâmetro tags escalar com um erro de validação claro antes de criar o revisável, ou normalizá-lo se esse for o comportamento de compatibilidade pretendido. Um revisável malformado existente também deve falhar graciosamente em vez de causar um 500 não tratado durante a moderação.
Contorno e limitações deste relatório
Editar o revisável, remover a tag antiga, selecionar a tag existente macos e salvar alterou payload.tags para uma matriz de objetos de tag. A leitura posterior confirmou versão 1, ainda pendente, e a interface exibiu uma tag novamente. Não tentei a aprovação novamente após essa alteração.
O cliente do remetente original é desconhecido. Este relatório não estabelece que o compositor nativo gera tags escalares. Ele se baseia na requisição real, no revisável armazenado, na exceção e no código inspecionado; não o reproduzi separadamente em uma instalação limpa.
Para uma reprodução de desenvolvimento, o caminho a testar é: exigir aprovação para uma publicação de um usuário não-staff, enviar POST /posts com um escalar tags: "macos" e outros campos válidos, e então aprovar a publicação resultante na fila como administrador.
Há uma discussão mais antiga da API com a mesma exceção de subtração de String. Este relatório foca no valor inválido sendo aceito na fila de revisão e quebrando a aprovação posteriormente.