Troubleshooting BetterShield: common problems and fixes
Find the message BetterShield is showing you, see why it appears, and fix it: lockouts, emails, fixes, file checks, scheduled tasks, passkeys and more.
Start from what you see. Each section below quotes the message BetterShield shows, says why it appears, and what to do about it. Most of them also open a finding on BetterShield › Findings, so the same problem shows up there with its severity. If yours is not here, see Getting help.
Failed sign-ins are not being counted, so password guessing is not stopped
What you see: the finding Failed sign-ins are not being counted, so password guessing is not stopped (High). On BetterShield › Protection › Login & Access, the How this site sees you card starts “Lockouts are not running on this site yet.”
Why: BetterShield only locks out a visitor address it can verify. When requests reach WordPress from a private address (a reverse proxy, load balancer or container network in front of the site) and nothing names that proxy, every visitor seems to come from the same place. Locking that address would lock everyone out, you included, so lockouts stand down. The public form limits record those visitors but never close a form to them.
What to do:
- Add your proxy’s address or range under Addresses of your CDN or proxy on the same screen. Lockouts start working straight away.
- If the proxy is already named, the card says it “sends no forwarding header naming the visitor behind it”. Set the proxy to send an X-Forwarded-For header.
- Cloudflare needs no entry. If the card says the request “arrived through Cloudflare, and nobody has told this site it is behind Cloudflare”, lockouts are running, counted against Cloudflare’s address and the visitor’s together. Press Yes, this site is behind Cloudflare so a lockout follows the visitor alone.
- If it says “This site is set to trust Cloudflare, and this request did not arrive through it”, press Turn that off if the site is no longer behind Cloudflare.
You or a visitor is locked out
What you see: on the sign-in form, “Too many failed sign-ins from this connection.” or “Sign-in is not available from this connection.”
Why: the first is the attempt limit. By default, 5 wrong passwords in 15 minutes pause that connection for 15 minutes, twice as long for each repeat within a day, up to a day. The second means the connection matches an entry on Never allowed to sign in.
What to do:
- Wait. A pause ends on its own.
- Use the unlock email. An automatic notice is sent for a network the account used within the last 30 days, or when its correct password was used. On a new connection, choose Email Me an Unlock Link on the sign-in screen and enter your username or email address. When the lockout qualifies, open the link sent to the saved account address and press Clear the Lockout.
- Release it from the dashboard. An administrator can press Release Now in the Lockouts list on Protection › Login & Access. Add an address you trust to Always allowed and it is never locked out.
- Refused outright? Remove the matching entry from Never allowed to sign in.
- Nobody can sign in to release you? Use your recovery link, a recovery code or
wp bettershield recover. See Locked out.
A fix is not available, did not apply or did not undo
Fixes live on BetterShield › Protection › Hardening and under Signing in on Protection › Login & Access.
| What you see | Why | What to do |
|---|---|---|
| Not available here, and the preview says This cannot be applied on this site: with a reason | This site cannot support the fix, for example .htaccess rules on nginx, or Strict HTTPS (HSTS) on a site whose address is plain HTTP. | Follow the reason given. For .htaccess, see the next section. |
| “There is no working way back in: the recovery link is missing, expired or was not delivered, and no recovery codes are left.” | A fix that changes how people sign in needs a working way back first. | Generate a recovery link or issue recovery codes under Protection › Recovery, then apply the fix. Go ahead anyway applies it regardless, and is logged. |
| “The recovery options were last checked more than a day ago.” | The same check, gone stale. | Press Check readiness now under Protection › Recovery. |
| “The change was not applied: the directory is not writable.” (or “the file is not writable”, “the file could not be written”) | WordPress cannot write the file the fix needs. | Ask your host to let WordPress write to that folder or file, then apply again. |
| “The change was not applied because its undo record could not be written.” | The undo record is written first, and without it nothing changes. | See the storage section below. |
| “The last undo did not complete:” with a reason, then “Undo again to retry.” | The undo stopped part way. | Deal with the reason, then press undo again. |
| “The block in [file] has been edited since this plugin wrote it, so it was left alone rather than overwritten.” | Someone changed BetterShield’s rules in that file. | Keep anything that was added, then remove the block by hand. |
| “[Plugin] already does this with a setting of its own.” | Another security plugin already does the same job. | Leave it to one of them. |
See Hardening.
The .htaccess fixes do not work on nginx, IIS or OpenLiteSpeed
What you see: Uploads code block and Private file protection show Not available here, with “This site runs on nginx, which does not read .htaccess files, so this fix cannot work here.” (or IIS). On a server that does not name itself, they apply with the note “This server did not identify itself as one that reads .htaccess files.” On OpenLiteSpeed they say it “reads only rewrite rules from .htaccess files and skips the kind this fix writes”, and on LiteSpeed they apply with a note that enforcement could not be confirmed.
Why: these two fixes work by writing .htaccess rules, which Apache and LiteSpeed’s paid edition read, and nginx, IIS and OpenLiteSpeed ignore. BetterShield does not claim a protection the server will never enforce.
What to do: ask your host to add the same rules to the server configuration. The other fixes need no server rules, and Folder listing protection works on every server. Once BetterShield has kept a copy of a replaced file on nginx, IIS or OpenLiteSpeed, you may also see Files in quarantine can still be opened from the web (Medium): ask your host to deny web access to wp-. Nothing on your site loads from that folder. See Server compatibility.
Alert or recovery emails do not arrive
What you see: no alerts, a recovery link that never came, or “Alert could not be delivered” in the activity log.
Why: BetterShield sends through WordPress’s own mail. If WordPress cannot send mail, neither can BetterShield.
What to do: on BetterShield › Settings › Email Alerts, press Send a Test Alert and read the answer.
| Answer | What to do |
|---|---|
| “Handed to WordPress for sending” | Look in spam. If it never arrives, mail is leaving WordPress but not reaching you: check your mail setup with your host. |
| “The mail server did not accept it.” | The server’s mail configuration is refusing it. Set up sending with your host or a mail plugin. |
| “Alerts are muted, so nothing was sent.” | Unmute alerts, then test again. |
| “There is nowhere to send it: no address is named and the site has no admin email.” | Add a recipient. |
| “A test was sent a moment ago.” | Wait a few minutes. |
For recovery, if the recovery email cannot be sent, use recovery codes instead. On Protection › Recovery, “The link’s email could not be sent. Generate a new one and store it now. This cancels the old one.” means you should generate a new link and store the copy shown on screen. Recovery codes work without email, and Send a weekly recovery email check tests the mail path once a week. See Email alerts and Locked out.
The file check could not run
What you see: on BetterShield › Activity › File changes, messages such as “The official checksums for version [x] could not be fetched just now, so core files were not compared this time. This is usually temporary.” or “The checksums could not be fetched. This is a connection problem, not a finding about your site.” A file marked Could not be read. The finding Your WordPress and plugin files haven’t been checked for changes yet (Medium).
Why: the check compares your files with the copies WordPress.org publishes, so it needs to reach WordPress.org. A file the server will not let WordPress read cannot be compared. A check that could not run is never reported as clean.
What to do: allow the site to make outbound HTTPS requests to WordPress.org, then press Check now. For an unreadable file, ask your host to make it readable. On a large site the check runs in the background across several passes. See File changes and What BetterShield contacts.
BetterShield’s background jobs have stopped running
What you see: the finding BetterShield’s background jobs have stopped running (Medium). Other signs: Unusual for this site on the Overview saying “An hourly task went [time] between runs”, Scheduled audits on Settings › General saying an audit “has not run yet”, or “The last email test is overdue. Check your WordPress scheduled tasks.”
Why: WordPress runs scheduled tasks when a page load triggers them. A quiet site, or a host that turned that off without running the tasks another way, leaves them waiting: the daily audit, the file check, the weekly summary and housekeeping. BetterShield runs what it can when an administrator opens the dashboard and asks the site to run the rest, but that is a rescue, not a schedule.
What to do: ask your host to run WordPress’s scheduled tasks every few minutes with a system cron, calling wp-cron.php or wp cron event run --due-now. If one is already set up and the finding stays, that cron job is failing, and its log says why.
Protection is paused
What you see: on the Overview and each Protect tab, Protection is paused. “Every protection that runs inside WordPress is paused until [time]. Settings are untouched.” On Hardening it adds that the rules written into files stay in force. An incident response or an assistant’s change to sign-in may be refused until safe mode ends.
Why: someone opened a recovery link or a recovery code, or ran wp bettershield recover. Safe mode pauses BetterShield’s protections for one hour by default and changes no setting. Rules it wrote to .htaccess and index files stay in place.
What to do: if you expected it, let it end, or press End safe mode now on the Overview or a Protect tab (wp bettershield recover --end does the same; a pause from the network’s link is ended from Network Admin, see Locked out). If you did not, look on BetterShield › Activity for “Safe mode started” to see when it began, then generate a new recovery link under Protection › Recovery. See Locked out.
Passkeys are unavailable
| What you see | What to do |
|---|---|
| “Passkeys need HTTPS. Browsers refuse to create or use one on an insecure connection, so this stays switched off while this site is addressed over plain HTTP.” | Move the site to HTTPS. On a local site, localhost works. |
| “This server is missing the OpenSSL extension, which is needed to check a passkey signature.” | Ask your host to enable PHP’s OpenSSL extension. |
| “This browser does not support passkeys. Try a current version of Chrome, Safari, Edge or Firefox.” | Use a current browser. |
| “The browser refused: passkeys need a trusted HTTPS connection to this exact address. Nothing was changed.” | Open the dashboard at the site’s own HTTPS address, not another domain that points to it. |
| “This device already holds a passkey for this account.” | Use that passkey, or remove it and add it again. |
| “This account already has 10 passkeys, which is the limit.” | Remove one before adding another. |
If no prompt appears after a while, look for a password manager such as LastPass, 1Password or Bitwarden asking in its own window. See Passkeys.
The sign-in puzzle is unavailable
What you see: under Ask for a sign-in puzzle after wrong passwords on Protection › Login & Access: “Needs HTTPS. Your site isn’t using HTTPS yet, so this is off.” Sign-ins on ordinary HTTP skip this check. A visitor without JavaScript sees “That didn’t work. Check your username or email and your password. If they’re right, turn on JavaScript or wait a few minutes.”
Why: browsers only run the calculation on HTTPS or localhost, and it needs JavaScript.
What to do: move the site to HTTPS. A visitor without JavaScript can wait a few minutes and try again: the check lifts on its own, and an unsolved puzzle never counts toward a lockout. See Login & Access.
A two-factor code is refused
What you see: on the Authenticator app code or backup code screen, “That code does not match.” or “Too many wrong codes for this account in the last hour, so codes are not being checked for now.” or “That sign-in took too long, or was already used. Please sign in again from the beginning.”
Why:
- Time. Codes change every thirty seconds. BetterShield accepts the code for the current thirty seconds and the ones either side, so a phone whose clock is further out than that shows codes the site does not accept.
- Once per code. A code that has already signed someone in is refused, and so is an older one. Wait for the next code.
- The hourly cap. After ten wrong codes for an account in an hour, codes for that account are not checked for a while, on the sign-in screen and the setup screens alike.
What to do: set the phone’s date and time to automatic, then use the code it shows now, or an unused backup code. Still stuck? Your recovery link pauses the two-factor step, and an administrator can turn two-factor off for an account. See Two-factor and passkeys and Locked out.
AI explanations are unavailable
What you see: no Explain This in Plain Language button on findings. The Plain-language explanations card on Settings › General says why.
| Message | What to do |
|---|---|
| “Requires WordPress 7.0.” | Update WordPress. |
| “AI features are switched off for this site.” | WordPress’s own AI features are off on this site. Turn them on to use explanations. |
| “No AI provider is connected to this site.” | Connect a provider under WordPress’s Settings › Connectors. BetterShield never asks for or stores a key of its own. |
| “The explanation could not be generated. This is a problem with the AI provider, not with your site” | Check your provider’s connection, then ask again. The finding is unchanged. |
| “That is as many explanations as one account asks for in an hour. Try again shortly.” | The card shows the hourly limit for each account. |
The assistant connection test fails
On BetterShield › Agents › Connect, under Connection health, Test connection makes one real call and says where it stopped.
| Result | What to do |
|---|---|
| “The connection is switched off here, so nothing answered.” | Turn it on, then test again. |
| “Nothing is paired yet, so there was no credential to try.” | Press Connect, then test again. |
| “This site could not reach its own address.” | Your host refuses requests a site makes to itself. An assistant connecting from outside may still get through. |
| “The certificate could not be verified from this server.” | Usual on a local or staging site. On a live site, check the certificate. |
| “The address redirected somewhere else.” | Make the site address and WordPress address agree, both on https. |
| “The address answered with a page instead of the endpoint, so it is not routed to this plugin.” | Save Settings › Permalinks once to rebuild the rules, then test again. |
| “The credential was refused.” | Press Rotate, then put the new credential into your assistant. |
| “The round trip worked and nothing was offered.” | Turn on read access for agents. |
If step 1 says Requires WordPress 6.9., BetterShield’s own copy of the Abilities API is missing: reinstall BetterShield from WordPress.org, or update WordPress to 6.9 or newer. With plain permalinks, the browser sign-in flow for Claude and ChatGPT is not available; the other clients still work. See Connect an AI assistant.
Part of the plugin’s storage is unavailable
What you see: an Overview card, Part of this plugin’s storage is unavailable, naming what is affected (such as The activity log or Sign-in lockouts), with Repair. After an hour, the finding Part of this plugin’s storage has been unavailable for more than an hour (High). If the affected part counts code guesses, the finding Sign-ins are being refused because BetterShield cannot save to the database (Critical) appears, and two-factor, backup and recovery codes are refused until it is fixed. The recovery link still works.
Why: a table or column BetterShield creates for itself is missing, usually after an update the database did not finish. The part that writes there stops; everything else carries on. BetterShield tries again every hour on its own.
What to do: press Repair. It only creates what is missing and touches no existing data. If it answers “The migration ran again and did not finish:” with the database’s reply, ask your host whether the database account may create tables. Deactivating and reactivating BetterShield runs its installer again.
Another security plugin is detected
What you see: Quick Setup shows Another security plugin is active, with one row for each job both plugins do. On Hardening, a fix may say “[Plugin] already does this with a setting of its own. Applying it here as well does the same job twice; leave it to one of them.”
Why: two plugins limiting sign-in attempts can lock a person out twice, and two asking for a second factor ask twice. If BetterShield’s Sign-in attempt limits is on and another active plugin also limits sign-in attempts without the choice being made here, the audit opens Two plugins limit sign-in attempts (Low).
What to do: choose who keeps each job, then press Save choices.
| Job | Choices | Default |
|---|---|---|
| Sign-in attempt limits | Keep [plugin] (BetterShield’s own limit goes off) or Use BetterShield | Keep |
| Two-factor | Keep [plugin] (anyone already enrolled keeps signing in as now) or Use BetterShield | Keep |
| Activity log | Keep both or Use BetterShield only | Keep both |
| File change monitoring | Keep both or Use BetterShield only | Keep both |
Sign-in address, firewall and scanner rows are stated, not chosen. BetterShield never switches another plugin off: deactivate it yourself from the Plugins screen when you are ready. To change your answers later, press Run Quick Setup again on Settings › General. See Run alongside another security plugin.