WooCommerce 10.9 records transactional email outcomes, while WordPress can also fire wp_mail_failed when PHPMailer rejects a message. When custom callbacks log asynchronously or reuse a global order value, the two records can look like separate failures even though they describe one send attempt.
Use this when the WooCommerce transactional-emails log says an email was sent but wp_mail_failed recorded an error, when duplicate failure alerts appear, or when support cannot match an order to the provider message ID.
Quick answer
WooCommerce Transactional Email wp_mail_failed Race Audit should be handled with a narrow evidence-first workflow: create one trace id, record both hooks, match provider timing, then verify the result before making broader changes.
What to check first
- Create one staging order and record the order ID, email class, request ID, and exact trigger time.
- Add a temporary wp_mail_failed callback that records only the error code, timestamp, and request ID.
- Compare the callback timestamp with the WooCommerce transactional-emails log and SMTP provider event.
- Check whether a retry or background action reused the original order ID after the first attempt ended.
- Remove the temporary callback after one failed and one successful controlled test.
Diagnostic table
Use this table to keep the work practical. It connects the symptom to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Create one trace ID | Create one staging order and record the order ID, email class, request ID, and exact trigger time. | One controlled attempt has one order ID, email class, request ID, and provider outcome. |
| Record both hooks | Add a temporary wp_mail_failed callback that records only the error code, timestamp, and request ID. | The log order explains the timing without treating the same attempt as two incidents. |
| Match provider timing | Compare the callback timestamp with the WooCommerce transactional-emails log and SMTP provider event. | A successful retry creates a separate trace and does not overwrite the failed attempt. |
| Separate retries | Check whether a retry or background action reused the original order ID after the first attempt ended. | No recipient address, message body, token, or payment data remains in debug logs. |
Why this usually happens
- WooCommerce and WordPress observe different layers of the same mail attempt.
- A provider can accept a message after WordPress has finished, so delivery evidence arrives later.
- Custom loggers can write out of order when queue workers or remote APIs are involved.
- A broad callback can capture unrelated site email and make the incident appear larger.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
add_action( 'wp_mail_failed', function ( $error ) {
error_log( wp_json_encode( [
'at' => gmdate( 'c' ),
'code' => $error->get_error_code(),
'request_id' => $_SERVER['HTTP_X_REQUEST_ID'] ?? 'none',
] ) );
} );
# Do not log recipients or message bodies.
Safe fix order
Do the work in a sequence that makes each result easy to prove. Stop if a step produces new evidence that changes the incident scope.
- Create one trace ID
- Record both hooks
- Match provider timing
- Separate retries
- Remove debug code
What to tell the client or owner
Share the order ID, redacted email class, request ID, UTC timestamps, WordPress error code, WooCommerce result, SMTP message ID, and retry result.
Production verification checklist
- One controlled attempt has one order ID, email class, request ID, and provider outcome.
- The log order explains the timing without treating the same attempt as two incidents.
- A successful retry creates a separate trace and does not overwrite the failed attempt.
- No recipient address, message body, token, or payment data remains in debug logs.
Mistakes to avoid
- Do not judge the fix by one browser or the homepage only.
- Do not delete evidence before recording usernames, file paths, timestamps, and response headers.
- Do not add a cache, security, or tracking plugin while the original problem is still unclear.
- Do not leave test users, temporary debug logs, or broad API keys active after verification.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, malware risk, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, trace WooCommerce email delivery.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Helpful references