There are many different situations in which a block error notice might be shown to a user, and the message is often different depending on the situation.
Error messages also differ depending on the features of the block. A few examples:
- The desktop editing message differs according to the type of block (DatabaseBlock, SystemBlock, etc), whether the block is an autoblock, and whether it is partial/sitewide
- The Special:EmailUser message differs according to whether the block is partial/sitewide
- The Special:CreateAccount message differs according to whether the block is against an IP range or not
How block errors are made
Block errors are reported using a message key and formatted block details to pass in as message parameters.
AbstractBlock::getBlockErrorParams() returns an array of parameters, and AbstractBlock::getPermissionsError() adds an error message key to the array. The different block types use different message keys, which pass in different parameters. Additionally, ApiBlockInfoTrait::getDetails() returns an array of block error parameters, independently of AbstractBlock::getBlockErrorParams(). (These two methods each return a different set of parameters, so different information about the block is available in different situations.)
The information for the error message is built in the following different ways:
- Call AbstractBlock::getPermissionsError(), or throw a UserBlockedError, which calls AbstractBlock::getPermissionsError() (example: desktop editing)
- Call AbstractBlock::getBlockErrorParams() directly, and add a custom message key to the array (example: emailing)
- Get block error params from ApiBlockInfoTrait::getBlockDetails() and create a custom message (example: mobile editing)
- Get information about the block directly (e.g. by calling $block->getId(), $block->getReason(), etc) and create a custom message (example: account creation)
Making block errors more consistent
Thinking about long-term stability, it could be helpful if block message creation were more centralized. However, we should be careful to allow for flexibility and customization where appropriate.
- We could define a superset of details that can describe any block, and make sure that AbstractBlock::getErrorParams() and ApiBlockInfoTrait::getBlockDetails() get these from the same place. Messages could then choose which of these details to use.
- We could try to re-route places where errors are built using (2) and (4) to use (1) and (3). E.g. we could restructure the block messages so that they always show the same details for a particular type of block (DatabaseBlock, SystemBlock, etc) - or no details at all where appropriate - and add a custom prefix (e.g. "You have been blocked from using email", "You have been blocked from creating an account", etc).
- We could make some kind of formatting layer between the block object and the error. We could move AbstractBlock::getErrorParams() and AbstractBlock::getPermissionsError() to this layer, thus moving the context/language dependency out of blocks (and potentially addressing other language-related problems such as T227007).
- Create a block error formatting service and move the logic for formatting error params and building the final error message array to this service
- A method on the block classes returns a set of normalised, unformatted error params (e.g. as an associative array/object); the params should be consistent with a predefined interface
- The service accepts a block object and some information about the context (perhaps a message key?) and builds an error message array based on these
- T225939: System and composite block messages on mobile contain confusing information
- T227110: Provide more informative block error message for Special:CreateAccount
- T226990: Block messages are inconsistent if a user is blocked from email
- T227412: Partial blocks leads to wrong error messages
- T233206: Block message for partial blocks is potentially misleading