Error TypeError al enviar una bandera con contenido personalizado (banderas require_message)

Descripción del error

Cuando un usuario selecciona un tipo de reporte que requiere un mensaje personalizado (por ejemplo, notify_moderators, notify_user o cualquier reporte personalizado creado por un administrador con la opción “Requerir mensaje” activada), completa el mensaje y lo envía, el navegador lanza un TypeError no capturado y el reporte nunca se envía.

Pasos para reproducir

  1. Visita cualquier publicación de un tema.
  2. Haz clic en el botón de reporte para abrir el modal de reportes.
  3. Selecciona un tipo de reporte que requiera un mensaje (por ejemplo, “Otra cosa” / notify_moderators, o cualquier reporte personalizado creado en Administración → Reportes con la opción “Requerir mensaje” activada).
  4. Escribe un mensaje en el área de texto (lo suficientemente largo para superar la longitud mínima).
  5. Haz clic en el botón de enviar.

Comportamiento esperado

El reporte se envía correctamente.

Comportamiento real

El modal de reporte se cierra, pero el reporte no se envía. La consola del navegador muestra:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'act')
    at n.create (flag.js:24:8)
    at S.createFlag (flag.gjs:205:32)
    at S.takeAction (flag.gjs:196:12)
    at m.perform (reviewable-bundled-action.gjs:47:17)
    at ej._boundaryActionHandler (select-kit.js:685:34)
    ...

Análisis de la causa raíz

El fallo se origina en Flag#create (flag.js:24):

create(flagModal, opts) {
  const postAction = this.postActionFor(flagModal); // devuelve undefined
  // ...
  postAction.act(...) // ← TypeError: Cannot read properties of undefined
}

postActionFor en PostFlag busca el reporte seleccionado por su id numérico dentro de actions_summary:

// post-flag.js
postActionFor(flagModal) {
  return flagModal.args.model.flagModel.actions_summary.find(
    (item) => item.id === flagModal.selected.id
  );
}

El PostSerializer del backend solo incluye una entrada de reporte en actions_summary cuando al menos uno de can_act, count o acted es verdadero:

result << summary if summary[:can_act] || summary[:count] || summary[:acted]

Para los reportes con require_message: true (que son todos notify_type: true), post_can_act? establece can_act: false cuando already_did_flagging es verdadero; es decir, cuando el usuario ya ha enviado algún reporte de tipo notificación en esa publicación. En ese caso, la entrada está ausente en actions_summary, postActionFor devuelve undefined y se produce el fallo.

Mientras tanto, Post#flagsAvailable (que controla qué puede seleccionar el usuario en la interfaz) utiliza el mapa actionByName construido al cargar la página, por lo que el reporte puede seguir apareciendo como seleccionable incluso después de que actions_summary ya no lo contenga.

Error secundario

También hay una comparación incorrecta en flag.gjs:

const NOTIFY_MODERATORS_KEY = "notify_moderators"; // cadena

get notifyModeratorsFlag() {
  return this.flagsAvailable.find((f) => f.id === NOTIFY_MODERATORS_KEY);
  //                                      ^ número   ^ cadena — siempre falso
}

f.id es un número, pero NOTIFY_MODERATORS_KEY es una cadena, por lo que === siempre devuelve false y notifyModeratorsFlag siempre es undefined. Esto rompe la lógica del botón “Reportar para revisión” en flagForReview().

Solución sugerida

PostFlag#postActionFor debería utilizar el mapa actionByName (indexado por name_key) en lugar de buscar en actions_summary por id, de manera coherente con cómo ya funciona TopicFlag#postActionFor:

// post-flag.js
postActionFor(flagModal) {
  return flagModal.args.model.flagModel.actionByName[
    flagModal.selected.name_key
  ];
}

Y notifyModeratorsFlag debería comparar por name_key en lugar de por id:

get notifyModeratorsFlag() {
  return this.flagsAvailable.find((f) => f.name_key === NOTIFY_MODERATORS_KEY);
}

Versión de Discourse

2026.5.0-latest

Reproducible en

  • Última rama main
2 Me gusta

Gracias por el informe, lo revisaremos. Si lo deseas, no dudes en enviar también un PR.

Intenté reproducirlo localmente, pero no logré hacerlo. ¿Puedes reproducirlo si activas el modo seguro?

1 me gusta

Creo que marcar el tema una vez no causará esto, ya que entonces already_did_flagging debería ser false. Por lo general, no es posible volver a marcar la misma publicación. Sin embargo, después de marcarla como „algo más“, todavía se puede marcar como „ilegal“. El resultado en este caso es

1 me gusta

Ahora logré reproducirlo con éxito:

Aunque por lo general no es posible marcar la misma publicación dos veces, esto parece ser diferente en los temas anidados. Así que:

  1. Crea un tema con algunas respuestas anidadas.
  2. Marca la respuesta como “otra cosa” y envía la señal.
  3. Haz clic nuevamente en el ícono de señal.
    Resultado esperado: Solo debería estar disponible “Es ilegal”, igual que en las publicaciones de temas sin modo anidado.
    Resultado real: Todas las razones para señalar, excepto “otra cosa”, están disponibles.
  4. Elige otra razón, envía la señal y revisa la consola del navegador.
1 me gusta