El parámetro de etiquetas Scalar aceptado en la cola de revisión causa un error HTTP 500 al aprobar

La aprobación de un tema en cola en nuestro sitio autoalojado falló con HTTP 500 porque el registro en cola contenía payload.tags = "macos" (una cadena de caracteres). El valor malformado ya había sido aceptado por POST /posts.

Entiendo que los clientes deben enviar una matriz de etiquetas. El problema que estoy reportando es que un escalar inválido puede ser aceptado en la cola de revisión y solo falla más tarde, cuando un moderador aprueba la publicación.

Versión: 2026.10.0-latest, commit 3f2bf92368c78a7fa9a755f3d046adf35dd4459b.

Evidencia del incidente

La publicación requería aprobación debido a approve_post_count.

A las 13:37:52 UTC del 2026-10-22, los parámetros originales de la solicitud Rails ya contenían:

"tags" => "macos"

La solicitud fue POST /posts y el correspondiente registro de acceso registró HTTP 200. Los nombres de parámetros enviados fueron title, raw, category y tags.

La lectura de la revisable pendiente confirmó:

{
  "type": "ReviewableQueuedPost",
  "status": 0,
  "version": 0,
  "topic_id": null,
  "payload": {
    "tags": "macos"
  }
}

Este es un extracto de campos relevantes, con el título, el cuerpo y la información del usuario omitidos. La interfaz de revisión mostró la etiqueta como cinco letras separadas: m, a, c, o, s.

Hacer clic en Aprobar produjo esta excepción (cinco ocurrencias agrupadas en los registros):

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

Estos son los caminos de código verificados en el contenedor en ejecución en el commit anterior:

  • PostsController#create_params llama a params.permit(tags: %i[id name]), pero no usa los parámetros filtrados devueltos. Luego asigna el valor original con result[f] = params[f].
  • NewPostManager#enqueue copia @args[:tags] directamente en la carga útil de la revisable.
  • ReviewableQueuedPost#create_options convierte las etiquetas solo cuando el valor ya es una Matriz, dejando una cadena de caracteres escalar sin cambios.
  • DiscourseTagging.tags_for_saving luego evalúa tags_arg - tag_names cuando el usuario que aprueba puede crear etiquetas, lo que lanza una excepción para una cadena de caracteres.

Comportamiento esperado

Rechazar un parámetro tags escalar con un error de validación claro antes de crear la revisable, o normalizarlo si ese es el comportamiento de compatibilidad previsto. Una revisable malformada existente también debería fallar graciosamente en lugar de causar un 500 no manejado durante la moderación.

Solución temporal y límites de este informe

Editar la revisable, eliminar la etiqueta antigua, seleccionar la etiqueta existente macos y guardar cambió payload.tags a una matriz de objetos de etiqueta. La lectura posterior confirmó versión 1, aún pendiente, y la interfaz volvió a mostrar una etiqueta. No he reintentado la aprobación después de ese cambio.

El cliente del remitente original es desconocido. Este informe no establece que el compositor nativo genere etiquetas escalares. Se basa en la solicitud real, la revisable almacenada, la excepción y el código inspeccionado; no lo he reproducido por separado en una instalación limpia.

Para una reproducción en desarrollo, el camino a probar es: requerir aprobación para una publicación de un usuario no personal, enviar POST /posts con un escalar tags: "macos" y otros campos válidos, y luego aprobar la publicación resultante en cola como administrador.

Hay una discusión de API anterior con la misma excepción de sustracción de String. Este informe se centra en el valor inválido siendo aceptado en la cola de revisión y rompiendo la aprobación más tarde.