{"id":367789,"date":"2026-09-18T15:51:48","date_gmt":"2026-09-18T15:51:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/faultwright-error-monitor-cron-email-failure-alerts\/"},"modified":"2026-09-20T18:34:09","modified_gmt":"2026-09-20T18:34:09","slug":"faultwright","status":"publish","type":"plugin","link":"https:\/\/bel.wordpress.org\/plugins\/faultwright\/","author":17599152,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1.1","requires":"6.4","requires_php":"7.4","requires_plugins":null,"header_name":"Faultwright \u2013 Error Monitor, Cron & Email Failure Alerts","header_author":"Emtiaz Zahid","header_description":"See every PHP error, JavaScript error, failed cron job, failed email and failed update on one screen, explained in plain English, with what changed before it started.","assets_banners_color":"cd896f","last_updated":"2026-09-20 18:34:09","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/emtiazzahid.github.io\/plugins\/faultwright\/","header_author_uri":"https:\/\/github.com\/emtiazzahid","rating":0,"author_block_rating":0,"active_installs":0,"downloads":88,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"emtiazzahid","date":"2026-09-20 18:34:09","revision":3704539}},"upgrade_notice":{"1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3702287,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3702287,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3702287,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3702287,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3702287,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3702287,"resolution":"1","location":"assets","locale":"","width":1280,"height":800},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3702287,"resolution":"2","location":"assets","locale":"","width":1280,"height":800},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3702287,"resolution":"3","location":"assets","locale":"","width":1280,"height":800},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3702287,"resolution":"4","location":"assets","locale":"","width":1280,"height":800},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3702287,"resolution":"5","location":"assets","locale":"","width":1280,"height":800},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3702287,"resolution":"6","location":"assets","locale":"","width":1280,"height":800}},"screenshots":{"1":"Issues list: every failure source in one place, grouped, with the likely component.","2":"Issue detail: plain-English explanation, what changed before it started, occurrences and stack trace.","3":"Timeline: errors and changes on one axis.","4":"Cron health: next run, overdue flags, durations and Run now.","5":"Dashboard widget with the 7-day sparkline.","6":"Settings: capture sources, early loader, notifications and privacy."}},"plugin_section":[262246],"plugin_tags":[4567,94,267,14925,5603],"plugin_category":[41,54,59],"plugin_contributors":[191403],"plugin_business_model":[],"class_list":["post-367789","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-cron","plugin_tags-debug","plugin_tags-email","plugin_tags-error-log","plugin_tags-monitoring","plugin_category-communication","plugin_category-security-and-spam-protection","plugin_category-utilities-and-tools","plugin_contributors-emtiazzahid","plugin_committers-emtiazzahid"],"banners":{"banner":"https:\/\/ps.w.org\/faultwright\/assets\/banner-772x250.png?rev=3702287","banner_2x":"https:\/\/ps.w.org\/faultwright\/assets\/banner-1544x500.png?rev=3702287","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/faultwright\/assets\/icon.svg?rev=3702287","icon":"https:\/\/ps.w.org\/faultwright\/assets\/icon.svg?rev=3702287","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/faultwright\/assets\/screenshot-1.png?rev=3702287","caption":"Issues list: every failure source in one place, grouped, with the likely component."},{"src":"https:\/\/ps.w.org\/faultwright\/assets\/screenshot-2.png?rev=3702287","caption":"Issue detail: plain-English explanation, what changed before it started, occurrences and stack trace."},{"src":"https:\/\/ps.w.org\/faultwright\/assets\/screenshot-3.png?rev=3702287","caption":"Timeline: errors and changes on one axis."},{"src":"https:\/\/ps.w.org\/faultwright\/assets\/screenshot-4.png?rev=3702287","caption":"Cron health: next run, overdue flags, durations and Run now."},{"src":"https:\/\/ps.w.org\/faultwright\/assets\/screenshot-5.png?rev=3702287","caption":"Dashboard widget with the 7-day sparkline."},{"src":"https:\/\/ps.w.org\/faultwright\/assets\/screenshot-6.png?rev=3702287","caption":"Settings: capture sources, early loader, notifications and privacy."}],"raw_content":"<!--section=description-->\n<p>\"The site was fine yesterday.\" Faultwright shows you what broke, when it started, which plugin is probably responsible, and what to do about it. No external account, no developer required.<\/p>\n\n<h4>Five failure sources, one timeline<\/h4>\n\n<ul>\n<li><strong>PHP errors<\/strong> \u2013 fatals, uncaught exceptions and warnings, with the file, line and a trimmed stack trace. An optional one-file early loader captures fatals raised while <em>other<\/em> plugins start up. New lines in debug.log are imported too.<\/li>\n<li><strong>JavaScript errors<\/strong> \u2013 a 1.4 KB collector (no cookies, no dependencies; sampling uses sessionStorage) reports browser errors, attributed to the plugin or theme that shipped the script. Browser-extension noise is filtered out.<\/li>\n<li><strong>Cron health<\/strong> \u2013 detects a dead WP-Cron, overdue events, events whose plugin was removed, and scheduled jobs that crash.<\/li>\n<li><strong>Email failures<\/strong> \u2013 every wp_mail failure plus SMTP-plugin errors, and a warning when orders or form entries happen but no email goes out.<\/li>\n<li><strong>Update failures<\/strong> \u2013 plugin, theme and core updates that could not be installed, auto-update failures and plugins that crash on activation.<\/li>\n<li><strong>REST \/ AJAX 5xx<\/strong> \u2013 API routes and admin-ajax actions that return server errors.<\/li>\n<\/ul>\n\n<h4>\"What changed right before it started\"<\/h4>\n\n<p>Faultwright keeps a change log: plugin and theme installs, updates, activations, deletions, theme switches, WordPress and PHP version changes, permalink and URL changes. Every issue shows the changes in the 48 hours before its first occurrence, ranked by likelihood.<\/p>\n\n<h4>Plain-English explanations<\/h4>\n\n<p>Over forty built-in explanations cover the errors people actually hit: memory exhausted, maximum execution time, undefined function, cannot redeclare, headers already sent, SMTP authentication, cURL timeouts, mixed content, \"$ is not defined\", chunk load errors and more. Each one says what it means, the likely cause, what to try, and when to contact a developer or your host.<\/p>\n\n<p>For anything else, an optional bring-your-own-key <strong>Explain with AI<\/strong> button sends the error details to OpenAI, Anthropic, Google Gemini or any OpenAI-compatible endpoint (Ollama, Groq, OpenRouter). Nothing is ever sent automatically.<\/p>\n\n<h4>Everything else<\/h4>\n\n<ul>\n<li>Issues grouped by fingerprint with count, first\/last seen, affected URLs and roles, Open \/ Resolved \/ Ignored status and notes. Resolved issues reopen automatically if the error comes back.<\/li>\n<li>Timeline of errors and changes on one axis (24h \/ 7d \/ 30d).<\/li>\n<li>Cron screen with next run, overdue flags, last duration and Run now (defers to WP Crontrol when installed).<\/li>\n<li>Dashboard widget with a 7-day sparkline and an admin-bar badge with the open critical count.<\/li>\n<li>Daily or weekly digest email and an immediate email for the first occurrence of a new critical issue (throttled). Both are on by default, go to the site admin email until you enter recipients, and can be switched off under Settings \u2192 Notifications.<\/li>\n<li>Site Health tests: cron running, no fatals in 7 days, emails sending.<\/li>\n<li>WP-CLI: <code>wp faultwright issues list<\/code>, <code>wp faultwright issues show &lt;id&gt;<\/code>, <code>wp faultwright cron check<\/code>, <code>wp faultwright changes list<\/code>, <code>wp faultwright prune<\/code>, <code>wp faultwright test-error<\/code>, <code>wp faultwright digest<\/code>.<\/li>\n<li>Privacy by default: error records hold no user IDs, email addresses, IP addresses or request bodies, and query strings are stripped from URLs. The change log records which logged-in user made a change. Retention is 30 days for events and 90 days for changes.<\/li>\n<li>Flood protection: per-request and per-minute caps, a file fallback if the database is unavailable, and a kill-switch constant.<\/li>\n<\/ul>\n\n<h4>Developer hooks<\/h4>\n\n<pre><code>faultwright_ignore_error, `faultwright_js_noise_patterns`, `faultwright_explanations`, `faultwright_severity`, `faultwright_event_recorded`, `faultwright_notification_channels`, `faultwright_capability`, `faultwright_ai_prompt`, `faultwright_retention_days`, `faultwright_mail_activity_count`.\n<\/code><\/pre>\n\n<h3>External services<\/h3>\n\n<p>Faultwright runs entirely on your own server. It has no telemetry, no account, no licence check and no update server of its own. The only time anything is sent to a third party is the optional \"Explain with AI\" feature described below.<\/p>\n\n<h4>Explain with AI (optional, off by default)<\/h4>\n\n<p>Some errors have no built-in explanation. For those, an administrator can turn on \"Explain with AI\" under Faultwright \u2192 Settings \u2192 Explanations, paste their own API key, pick a provider, and then press \"Explain with AI\" followed by \"Send\" on an individual issue. Nothing is sent automatically, on a schedule, or without that second click. Before sending, the screen shows which provider and model will be used and a rough token count.<\/p>\n\n<p>On each click, Faultwright sends one request containing:<\/p>\n\n<ul>\n<li>the error message (as produced by the failing code, so it may contain whatever that code put in it), its severity, source (PHP, JavaScript, cron, email, update or API) and the request type (front end, admin, cron, REST, AJAX, CLI);<\/li>\n<li>the file path and line number where the error occurred, and the file paths and function names from the stack trace (relative to your WordPress folder, never file contents, never function arguments);<\/li>\n<li>the plugin or theme Faultwright attributed the error to;<\/li>\n<li>your WordPress and PHP version numbers;<\/li>\n<li>your API key, in the authorisation header, so the provider can bill you.<\/li>\n<\/ul>\n\n<p>It does not send your site URL, page URLs, visitor roles, IP addresses, user accounts, email addresses, form data or database contents. The provider's reply is stored in your own database with the issue and is deleted with it. You can adjust or strip the prompt with the <code>faultwright_ai_prompt<\/code> filter.<\/p>\n\n<p>The request goes only to the provider you selected:<\/p>\n\n<ul>\n<li>OpenAI (api.openai.com) \u2013 Terms: https:\/\/openai.com\/policies\/terms-of-use \u2013 Privacy: https:\/\/openai.com\/policies\/privacy-policy<\/li>\n<li>Anthropic (api.anthropic.com) \u2013 Terms: https:\/\/www.anthropic.com\/legal\/commercial-terms \u2013 Privacy: https:\/\/www.anthropic.com\/legal\/privacy<\/li>\n<li>Google Gemini (generativelanguage.googleapis.com) \u2013 Terms: https:\/\/ai.google.dev\/gemini-api\/terms \u2013 Privacy: https:\/\/policies.google.com\/privacy<\/li>\n<li>OpenAI-compatible endpoint \u2013 any base URL you enter, for example a self-hosted Ollama, Groq or OpenRouter. Data goes to that server under that operator's terms and privacy policy, which you are responsible for reviewing. If the base URL is left empty this option sends to OpenAI.<\/li>\n<\/ul>\n\n<p>Your API key is stored encrypted in the WordPress options table using your site's authentication salts, is never displayed again beyond its last four characters, and is removed when you clear it or uninstall the plugin.<\/p>\n\n<h4>Everything else stays on your site<\/h4>\n\n<ul>\n<li>The browser error collector, loaded on front-end and admin pages when JavaScript capture is on, posts error messages, script URLs, line numbers, stack traces, the page URL with its query string removed and the viewport size to your own site's REST API only. Sampling is decided per browser session with sessionStorage; no cookies are set. Your server keeps the visitor's role and browser family, not IP addresses or full user-agent strings.<\/li>\n<li>Alert and digest emails go through your own site's wp_mail() to the addresses you enter, or to the site admin email if none are set.<\/li>\n<li>The plugin links to WordPress.org for reviews; following that link is an ordinary browser visit.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>faultwright<\/code> folder to <code>\/wp-content\/plugins\/<\/code> or install it from the Plugins screen.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Open <strong>Faultwright<\/strong> in the admin menu. Click <strong>Install early loader<\/strong> (recommended) and <strong>Send test error<\/strong> to confirm capture works.<\/li>\n<li>Optional: set digest recipients under Settings \u2192 Notifications and an AI key under Settings \u2192 Explanations.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20it%20record%20warnings%20that%20were%20silenced%20with%20the%20%40%20operator%3F\"><h3>Does it record warnings that were silenced with the @ operator?<\/h3><\/dt>\n<dd><p>Yes. Faultwright never reads or changes PHP's error-reporting level, so it cannot tell whether a call was wrapped in @. Warnings are grouped and counted, so a silenced call that fails repeatedly shows up as one group. Notices and deprecations are off by default and can be enabled in Settings.<\/p><\/dd>\n<dt id=\"does%20it%20slow%20my%20site%20down%3F\"><h3>Does it slow my site down?<\/h3><\/dt>\n<dd><p>No. When nothing goes wrong, the PHP handler costs well under a millisecond and no database queries run on the front end. The JavaScript collector is 1.4 KB and only talks to the server when an error happens. Sampling lets you record a fraction of front-end visitors.<\/p><\/dd>\n<dt id=\"do%20i%20need%20wp_debug%20on%3F\"><h3>Do I need WP_DEBUG on?<\/h3><\/dt>\n<dd><p>No. Faultwright captures errors directly. If WP_DEBUG_LOG is on, new lines in debug.log are imported as well and de-duplicated.<\/p><\/dd>\n<dt id=\"does%20it%20send%20data%20anywhere%3F\"><h3>Does it send data anywhere?<\/h3><\/dt>\n<dd><p>No. Nothing leaves your site unless you click \"Explain with AI\" with your own key configured. There is no telemetry.<\/p><\/dd>\n<dt id=\"what%20is%20the%20early%20loader%20file%3F\"><h3>What is the early loader file?<\/h3><\/dt>\n<dd><p>A tiny file copied into wp-content\/mu-plugins that loads Faultwright before every other plugin, so a fatal error raised while another plugin starts up is still captured. You can remove it from Settings \u2192 Capture at any time; uninstalling deletes it.<\/p><\/dd>\n<dt id=\"can%20it%20fix%20errors%3F\"><h3>Can it fix errors?<\/h3><\/dt>\n<dd><p>It explains them and points at the most likely culprit with the change history. Rolling a plugin back or contacting the author remains a manual step.<\/p><\/dd>\n<dt id=\"is%20it%20gdpr%20friendly%3F\"><h3>Is it GDPR friendly?<\/h3><\/dt>\n<dd><p>Error records store the visitor's role, never a user ID, email address or IP address. IP addresses are hashed (\/24) for rate limiting only and expire after one minute. Query strings are stripped from recorded URLs by default. Failed-email records keep the subject line and, optionally, the recipient domain, never the full address. The change log records which logged-in user activated, updated or changed something, so you can see who did what. The plugin adds a suggested paragraph to Settings \u2192 Privacy \u2192 Policy Guide.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20send%20anything%20to%20its%20author%3F\"><h3>Does the plugin send anything to its author?<\/h3><\/dt>\n<dd><p>No. Faultwright has no server of its own and sends no usage statistics or telemetry. Errors are stored in your own database; the browser collector posts to your own site's REST API. The only outbound requests are the optional AI explanations described under \"External services\", off until you enter your own API key.<\/p><\/dd>\n<dt id=\"where%20is%20the%20javascript%20source%3F\"><h3>Where is the JavaScript source?<\/h3><\/dt>\n<dd><p>The admin app and the browser collector ship un-minified in <code>assets\/src\/<\/code>; the files in <code>assets\/build\/<\/code> are produced from them with <code>npm install &amp;&amp; npm run build<\/code> (the <code>package.json<\/code> is included). Nothing else is compiled or obfuscated.<\/p><\/dd>\n<dt id=\"is%20this%20a%20developer%20tool%20like%20query%20monitor%3F\"><h3>Is this a developer tool like Query Monitor?<\/h3><\/dt>\n<dd><p>No. Query Monitor inspects a single request while you look at it. Faultwright is a persistent history for site owners and the people who maintain sites for them.<\/p><\/dd>\n<dt id=\"how%20do%20i%20disable%20capture%20without%20deactivating%3F\"><h3>How do I disable capture without deactivating?<\/h3><\/dt>\n<dd><p>Add <code>define( 'FAULTWRIGHT_DISABLE', true );<\/code> to wp-config.php.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Every PHP error, JavaScript error, failed cron job, failed email and failed update on one screen, explained in plain English, with what changed.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/367789","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=367789"}],"author":[{"embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/emtiazzahid"}],"wp:attachment":[{"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=367789"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=367789"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=367789"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=367789"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=367789"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/bel.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=367789"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}