Bug Description
When a user selects a flag type that requires a custom message (e.g. notify_moderators, notify_user, or any admin-created custom flag with “Require message” enabled), fills in the message, and submits — the browser throws an uncaught TypeError and the flag is never submitted.
Steps to Reproduce
- Visit any topic post
- Click the flag button to open the flag modal
- Select a flag type that requires a message (e.g. “Something Else” /
notify_moderators, or any custom flag created in Admin → Flags with “Require message” enabled) - Type a message in the text area (long enough to pass the minimum length)
- Click the submit button
Expected behavior
The flag is submitted successfully.
Actual behavior
The flag modal closes but the flag is not submitted. The browser console shows:
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)
...
Root Cause Analysis
The crash originates in Flag#create (flag.js:24):
create(flagModal, opts) {
const postAction = this.postActionFor(flagModal); // returns undefined
// ...
postAction.act(...) // ← TypeError: Cannot read properties of undefined
}
postActionFor in PostFlag looks up the selected flag by numeric id inside actions_summary:
// post-flag.js
postActionFor(flagModal) {
return flagModal.args.model.flagModel.actions_summary.find(
(item) => item.id === flagModal.selected.id
);
}
The backend PostSerializer only includes a flag entry in actions_summary when at least one of can_act, count, or acted is truthy:
result << summary if summary[:can_act] || summary[:count] || summary[:acted]
For require_message: true flags (which are all notify_type: true), post_can_act? sets can_act: false when already_did_flagging is true — i.e. the user has previously submitted any notify-type flag on that post. In that case the entry is absent from actions_summary, postActionFor returns undefined, and the crash follows.
Meanwhile Post#flagsAvailable (which controls what the user can select in the UI) uses the actionByName map built at page-load time, so the flag can still appear as selectable even after actions_summary no longer contains it.
Secondary bug
There is also a broken comparison in flag.gjs:
const NOTIFY_MODERATORS_KEY = "notify_moderators"; // string
get notifyModeratorsFlag() {
return this.flagsAvailable.find((f) => f.id === NOTIFY_MODERATORS_KEY);
// ^ number ^ string — always false
}
f.id is a number but NOTIFY_MODERATORS_KEY is a string, so === always returns false and notifyModeratorsFlag is always undefined. This breaks the “Flag for Review” button logic in flagForReview().
Suggested Fix
PostFlag#postActionFor should use the actionByName map (keyed by name_key) instead of searching actions_summary by id, consistent with how TopicFlag#postActionFor already works:
// post-flag.js
postActionFor(flagModal) {
return flagModal.args.model.flagModel.actionByName[
flagModal.selected.name_key
];
}
And notifyModeratorsFlag should compare by name_key instead of id:
get notifyModeratorsFlag() {
return this.flagsAvailable.find((f) => f.name_key === NOTIFY_MODERATORS_KEY);
}
Discourse version
2026.5.0-latest
Reproducible on
- Latest
mainbranch