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
- Visita cualquier publicación de un tema.
- Haz clic en el botón de reporte para abrir el modal de reportes.
- 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). - Escribe un mensaje en el área de texto (lo suficientemente largo para superar la longitud mínima).
- 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