Describe the Bug
The race condition causing duplicate WooCommerce orders via PayPal was reported as fixed in v3.4.1 (GitHub issue #3885), but the bug is still occurring in production as of March 12, 2026.
When a customer completes a PayPal checkout, multiple simultaneous PHP processes each independently create a separate WooCommerce order for the same PayPal transaction. PayPal charges the customer only once, but 3–4 WooCommerce orders are created with status "Processing", requiring manual intervention to cancel duplicates and reconcile stock.
The root trigger is consistent across all incidents: PayPal fires the CHECKOUT.ORDER.APPROVED webhook before WooCommerce has created a local order record. The plugin logs a warning — "WC order ID was not found in webhook event" — and multiple PHP processes then race to create the order simultaneously.
To Reproduce
- Add a product to the cart on a WooCommerce store running this plugin
- Proceed to checkout and select PayPal as the payment method
- Complete payment approval in the PayPal popup
- Observe WooCommerce orders — multiple duplicate orders are created for the same transaction
The issue appears more likely under normal server load and does not require any unusual conditions to trigger.
Screenshots
N/A — see log excerpts in Additional Details below.
Expected Behavior
One WooCommerce order is created per PayPal transaction. Duplicate orders do not occur.
Actual Behavior
3–4 WooCommerce orders are created per transaction. One order is "Failed", the rest are "Processing". PayPal is only charged once. Stock is reduced multiple times. Manual cleanup is required after every occurrence.
We have now had two separate customers affected:
- Incident 1: February 25, 2026 — 6 duplicate orders created
- Incident 2: March 12, 2026 — 4 duplicate orders created
Both incidents occurred before and after the supposed fix was released on March 5, 2026.
Environment
- WordPress Version: 6.9.4
- WooCommerce Version: 10.6.0
- Plugin Version: 3.4.1 (WooCommerce PayPal Payments)
- Browser: N/A — bug occurs server-side
- Other relevant plugins: N/A — isolated to PayPal checkout flow
Additional Details
Both incidents produce an identical warning in the plugin log immediately before the race condition occurs:
WARNING: WC order ID was not found in webhook event [WEBHOOK_ID] for PayPal order [PAYPAL_ORDER_ID]
The sequence of events each time:
T+0:00 - Customer completes PayPal approval. Single PayPal order created.
T+1:02 - CHECKOUT.ORDER.APPROVED webhook received from PayPal
T+1:05 - WARNING: WC order ID not found in webhook event (order not yet in DB)
T+1:08 - PHP process 1 → creates WC order A, patches PayPal order, attempts capture
T+1:08 - PHP process 2 → creates WC order B, patches PayPal order, attempts capture
T+1:09 - PHP process 3 → creates WC order C, patches PayPal order, attempts capture
T+1:11 - PHP process 4 → creates WC order D, patches PayPal order, attempts capture
T+1:11 - One process receives 500 INTERNAL_SERVICE_ERROR from PayPal → that order = Failed
T+1:12 - Remaining processes all receive 201 Created
T+1:15 - PAYMENT.CAPTURE.COMPLETED webhook confirms single charge only
Result: One PayPal charge, 3 WooCommerce orders in "Processing" status.
The fix in v3.4.1 has not resolved this. A server-side lock or mutex around the
order creation and capture flow is needed to prevent concurrent processes from
executing this code path simultaneously.
Describe the Bug
The race condition causing duplicate WooCommerce orders via PayPal was reported as fixed in v3.4.1 (GitHub issue #3885), but the bug is still occurring in production as of March 12, 2026.
When a customer completes a PayPal checkout, multiple simultaneous PHP processes each independently create a separate WooCommerce order for the same PayPal transaction. PayPal charges the customer only once, but 3–4 WooCommerce orders are created with status "Processing", requiring manual intervention to cancel duplicates and reconcile stock.
The root trigger is consistent across all incidents: PayPal fires the CHECKOUT.ORDER.APPROVED webhook before WooCommerce has created a local order record. The plugin logs a warning — "WC order ID was not found in webhook event" — and multiple PHP processes then race to create the order simultaneously.
To Reproduce
The issue appears more likely under normal server load and does not require any unusual conditions to trigger.
Screenshots
N/A — see log excerpts in Additional Details below.
Expected Behavior
One WooCommerce order is created per PayPal transaction. Duplicate orders do not occur.
Actual Behavior
3–4 WooCommerce orders are created per transaction. One order is "Failed", the rest are "Processing". PayPal is only charged once. Stock is reduced multiple times. Manual cleanup is required after every occurrence.
We have now had two separate customers affected:
Both incidents occurred before and after the supposed fix was released on March 5, 2026.
Environment
Additional Details
Both incidents produce an identical warning in the plugin log immediately before the race condition occurs:
WARNING: WC order ID was not found in webhook event [WEBHOOK_ID] for PayPal order [PAYPAL_ORDER_ID]
The sequence of events each time:
T+0:00 - Customer completes PayPal approval. Single PayPal order created.
T+1:02 - CHECKOUT.ORDER.APPROVED webhook received from PayPal
T+1:05 - WARNING: WC order ID not found in webhook event (order not yet in DB)
T+1:08 - PHP process 1 → creates WC order A, patches PayPal order, attempts capture
T+1:08 - PHP process 2 → creates WC order B, patches PayPal order, attempts capture
T+1:09 - PHP process 3 → creates WC order C, patches PayPal order, attempts capture
T+1:11 - PHP process 4 → creates WC order D, patches PayPal order, attempts capture
T+1:11 - One process receives 500 INTERNAL_SERVICE_ERROR from PayPal → that order = Failed
T+1:12 - Remaining processes all receive 201 Created
T+1:15 - PAYMENT.CAPTURE.COMPLETED webhook confirms single charge only
Result: One PayPal charge, 3 WooCommerce orders in "Processing" status.
The fix in v3.4.1 has not resolved this. A server-side lock or mutex around the
order creation and capture flow is needed to prevent concurrent processes from
executing this code path simultaneously.