Skip to content

Rate-limit error message is alarming and its countdown is stale for legitimate users #918

Description

@dknauss

Problem

The error shown when a user is blocked by the rate limiter has three UX problems that make a bad experience worse for legitimate users who simply mistyped their code.

Current message (class-two-factor-core.php line 1858):

ERROR: Too many invalid verification codes, you can try again in %s. This limit protects your account against automated attacks.

1. "ERROR:" prefix

The ERROR: label is the same severity indicator used for authentication failures and system errors. A user who mistyped their code three times is not in an error state — they are temporarily delayed. A softer label or no label at all would be more appropriate.

2. "automated attacks"

This phrase tells a confused, locked-out user that their account is being attacked. For a legitimate user who simply mistyped their verification code several times, this is alarming and inaccurate. The rate limit exists to protect against brute force, but the message is rendered for the person submitting the form, who is almost always the legitimate account holder.

3. Stale countdown

human_time_diff( $last_login + $time_delay ) is evaluated once at POST time and baked into the rendered HTML. The countdown shown ("try again in 2 minutes") does not update as time passes. A user who waits on the page has no way to know the lockout has expired without manually reloading. The message also gives no instruction to reload.

Suggested direction

Something like:

Too many incorrect verification codes. Please wait %s and try again.

Avoids the ERROR: prefix, drops the attack framing, and (with a reload instruction added) gives the user an actionable path forward. The exact wording should consider i18n and the existing translation strings.

Related

  • PR #917 — moves the rate-limit gate before provider pre-processing (the fix that surfaces this message to legitimate users more visibly)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions