Why Does PrestaShop Create Orders Even When Payments Fail?

Discovering failed or pending orders in your PrestaShop back office when no money was taken can be confusing, but it is rarely a sign of a broken storefront. In most cases, these records appear because PrestaShop creates the order entry the moment checkout is validated, before receiving final confirmation from the payment gateway.

When a payment declines, a webhook fails, or a customer abandons the redirect, the order gets left sitting in an incomplete or error state. Understanding how PrestaShop processes order states allows you to trace the exact cause, update your settings, and keep your inventory and sales reports accurate.

Why PrestaShop Logs an Order Before the Payment Succeeds

A PrestaShop failed order usually appears because the platform writes the order record before the gateway confirms payment. This is rarely a broken checkout: most cases trace back to a module calling validateOrder() too early, a missing or mismatched callback URL, or an order state mapped to the wrong place. Once you read the order state instead of guessing at modules, the cause is usually clear within minutes.

PrestaShop creates and validates an order as soon as a payment module callsvalidateOrder(), before the gateway confirms success. If the module or a webhook calls it prematurely, or the customer retries, orders appear with a "failed" or "awaiting payment" state instead of "payment accepted". They are real orders sitting in the wrong state, not phantom entries.

The mechanism lives in the PaymentModule class. Its validateOrder() method builds the order from the cart, assigns the initial order state, and triggers the confirmation email and stock handling. Only after that does control return to the gateway, so any later failure cannot undo the order; it can only change which state the order ends up in.

The confirmation step then depends on the customer returning to your shop with the order reference intact. When that return never happens, the order stays where the module left it: usually "awaiting payment" or the module's own failed state.

Symptoms You Are Dealing With PrestaShop Failed Orders

Before changing any settings, confirm that what you are seeing matches a state problem rather than an entirely broken checkout. These are the typical signs.

  • Orders appear in the Orders list with a state such as Payment error, Awaiting payment or Pending, even though no money was taken.
  • The customer's cart becomes empty after a failed payment, so they cannot simply retry without refilling it.
  • Stock quantities drop for an order that was never actually paid.
  • Order confirmation emails reach customers who never completed payment.
  • The same customer causes two order records for one purchase attempt.
  • The payment gateway dashboard shows a declined or abandoned transaction that PrestaShop knows nothing about.
  • Failed orders sit in the list for months because no one is sure whether they can be safely removed.
  • Sales and revenue reports include amounts that were never collected.

What Causes This Problem?

The cause is almost always one of a small number of state, module or configuration issues. The table below maps each cause to how it presents and how much effort it takes to resolve.

Cause Description Difficulty
Order Created Before Payment Confirmation PrestaShop generates an order record when checkout is validated, then updates its state once the payment module responds. If that response never arrives, the order stays in an intermediate state. Low (understanding it), Medium (fixing the state)
Wrong Default Order State For Failed Payments The payment module or order state settings assign the wrong state (for example, treating an error as a valid order), so failed payments look like real sales. Low
Payment Module Configuration Error Incorrect API credentials, sandbox mode left enabled, or a callback/webhook URL that does not match your store address, so the module never receives the payment result. Medium
Module or Theme Conflict Another module on the checkout page or a theme override interferes with the payment module's redirect or confirmation step. Medium
Caching and Page Cache Modules Cached checkout or confirmation pages serve stale content, so the customer's browser never reaches the endpoint that finalises the state. Low
Server or PHP Configuration Timeouts, restrictive firewall rules or an unsupported PHP version block the gateway's server-to-server notification. High
Customer Abandonment Mid-redirect The customer closes the tab or navigates back while being redirected to the gateway, leaving an order in a pending state that was never a real failure. Low
Duplicate Submissions Double-clicks or page refreshes on the confirmation step generate two order records for one attempt. Low

Quick Fixes to Try First

Start with these steps. They resolve the majority of everyday cases before you need to touch code or server settings.

  1. Open the order in question and read its current state carefully, noting the exact state name rather than assuming it is a failure.
  2. Check the payment gateway's own dashboard for that transaction reference. If the gateway shows a decline or no transaction at all, the order is genuinely unpaid.
  3. Confirm the payment module is not in test or sandbox mode. Test mode is a common reason real payments look like failures.
  4. Verify the callback or webhook URL configured in the payment module matches your live store URL exactly, including the https prefix.
  5. Change the affected order's state to Cancelled or the appropriate error state, so it drops out of your pending workflow.
  6. Clear the PrestaShop cache from Advanced Parameters, then Performance and purge any page cache or CDN cache in front of the store.
  7. Test a live checkout yourself with a low-value real transaction to see whether the state now resolves correctly.
  8. If stock was deducted for a cancelled order, restock the product from the order page.
  9. Disable email notifications for the failed state if customers are receiving confirmations they should not.

How Do I Stop PrestaShop Creating Orders For Failed Payments?

Fixing this is mostly a matter of tightening the points where the payment module hands control back to PrestaShop. Work through these in order, because the first three resolve most cases where failed orders keep appearing.

  1. Update the Payment Module to The Latest Release. Old versions of bank wire or card connectors can call the order-creation routine on an error response. Check the module's version against the PrestaShop Addons listing and update through the Module Manager.
  2. Confirm the Callback and Notification URLs. For hosted gateways, the return or webhook URL configured in the gateway dashboard must point to the module's validation controller on your store, and it must use HTTPS. A mismatch leaves the payment unconfirmed while an order already exists.
  3. Set A Sensible Default Order State For Failed Payments. In the payment module's configuration, point the failed or error status to a dedicated state such as Payment error rather than Awaiting payment or Processing. This keeps bad orders out of the states that trigger stock deduction and invoice generation.
  4. Enable Cart Auto-clean. Under Shop Parameters > Order Settings, turn on the option to clear abandoned carts after a set number of days, so stale carts tied to failed attempts do not linger and confuse reporting.
  5. Turn Off Sandbox or Test Mode. A gateway left in test mode can reject real transactions while still returning a response the module reads as a completed order.
  6. Audit Any Custom Or Third-party Modules. Search the module's code for calls to validateOrder(). It should only run after a confirmed successful payment, never inside an error or timeout branch.

If failed orders continue after these six steps, the cause is usually deeper: a core setting, a PHP or server issue, or a conflicting module. The diagnosis process below walks through those in a logical sequence. If you also sell tickets or run events alongside physical products, review how each order state behaves for the PrestaShop Events Module before changing defaults, so ticket orders are not accidentally caught by a new failed-payment rule.

One useful habit: after each change, place a genuine test order with a card you know will decline, then check whether a new entry appears under Orders. If the order count rises on a declined payment, the module is still calling the order routine too early.

1. The Order Was Created Before Payment Confirmation

This is the root of most confusion, and it is not a bug. PrestaShop builds the order record when the customer validates checkout, then relies on the payment module to move that record into a paid state once the gateway responds. If the gateway declines the card, the order never advances.

Identify it by opening the order and looking at the state history. A record whose history shows only the initial creation entry and no subsequent payment entry is a failed payment in the architectural sense. The fix is not to prevent the order from being created but to ensure the failure lands on the correct state.

  • Order state history shows entry into the store but no payment confirmation.
  • The order exists in the Orders list, but the gateway shows a declined transaction.

What is The Difference Between A Failed Order and A Real Order in PrestaShop?

The difference sits in one field: the order state. A failed order and a real order are the same record in the orders table until the state changes. What separates them is whether PrestaShop has moved that record to Payment accepted or left it somewhere earlier in the workflow.

Read the state column before you touch a single module. Store owners often assume a payment module is broken when the truth is simpler: the order exists, the money never arrived, and the state correctly reflects that. The state is the diagnosis.

Order state What it means Stock effect Customer email sent
Waiting for Payment Order created, payment not yet confirmed. Common with bank transfers, cheques and redirect gateways that have not returned. Stock deducted if "decrease on order creation" is set Order confirmation, depending on settings
Payment Error The gateway rejected the payment or the validation callback failed. This is a PrestaShop failed order in the strict sense. Usually deducted, then restored on cancellation Often yes, which confuses customers
Payment Accepted Money received and validated. This is a real order. Deducted Yes
Cancelled Order voided manually or by a module. Revenue excluded from most reports. Restored when set correctly Optional, depends on the state's email template

Two settings decide the real-world impact. In Shop Parameters > Order Settings, "Decrease product quantities" controls when stock moves, and the order state's own configuration controls whether an email fires. Get these wrong, and a failed payment quietly eats inventory and inflates your dashboard.

Revenue reports only count states flagged as paid, so a pile of Payment error orders will not show up in your sales totals. They will show up in your back office order list and in your customer's inbox. 

Root Causes: Why Modules Call Validate: Order() When Payment Fails

In PrestaShop, validateOrder() is the PaymentModule method that turns a cart into a real order. The problem is not that it exists: it is when a payment module calls it. If that call fires before the payment gateway confirms, the order exists regardless of whether money ever moved.

Six patterns account for most of these failed orders. Knowing which one you are looking at saves hours of module guessing.

  • Premature validateOrder() calls. A custom or outdated module calls the method at the wrong point, often straight after the redirect to the gateway instead of inside the confirmation callback. The order is created and the payment is not.
  • Misconfigured IPN or webhook URLs. The gateway sends its confirmation to an address that no longer resolves, for example after a domain change or a move out of a subfolder. The order waits in a pending state that never advances.
  • Server Timeouts on the callback. The gateway's notification hits a slow server, times out and retries. Each retry can leave another trace, especially when the module is not idempotent.
  • The Customer Clicking Pay Twice. An impatient double click on a slow checkout can submit two payment attempts against one cart. PrestaShop may register an order for each attempt.
  • 3D Secure Returns To A Stale Cart. The customer completes the bank challenge, comes back, and the browser restores an old cart context. The confirmation lands against a cart that no longer matches.
  • Test Or Sandbox Mode Left On. A module still pointing at the gateway's sandbox never processes a real payment, yet the order can still be created in the back office.

The first three are the ones worth checking first. They sit in the order-creation flow itself, not in the payment gateway, and they explain the majority of cases where a PrestaShop failed order appears with no matching transaction.

2. Module or Theme Conflict

Another module or a theme override can hijack the moment between the customer paying and PrestaShop recording the result. A one-page checkout module, a discount box, or an abandoned-cart tracker that hooks into the checkout page is the usual culprit.

The problem occurs because PrestaShop lets modules attach to the same hooks (the checkout footer, the payment step, the order confirmation). When two of them claim the same hook, one can stop the other from firing, and the failure state is never applied. Identify it by disabling non-essential modules on the checkout page one at a time, placing a declined test payment after each change. Once the order stops appearing, the last module you disabled is the trigger.

  1. Note every module that hooks into the checkout or payment step.
  2. Disable all of them except the payment module you are testing.
  3. Run a declined test payment and check whether an order is created.
  4. Re-enable the modules one by one, testing after each.
  5. When the failed order returns, you have found the conflicting module. Update it, replace it, or ask the developer for a fix.

A conflict that only appears on the live store, never in your test copy, is almost always a module that was enabled in production and never replicated to staging.

3. Caching & Page Cache

Cache modules and a CDN in front of the shop are excellent for speed and a frequent cause of stuck payment states. They serve a cached copy of the checkout or confirmation page, so the browser never reaches the live endpoint that finalises the order state.

You can spot it when a customer reports that they paid, the gateway shows a charge, but the order sits in Awaiting payment. The payment succeeded and the confirmation step was served from cache. Fix it by excluding the checkout, payment and order-confirmation controllers from every cache layer.

  • Purge the PrestaShop cache from Advanced Parameters, then Performance.
  • Add the checkout and confirmation URLs to the page-cache module's exclusion list.
  • Do the same in your CDN or reverse-proxy rules.
  • Retest a full payment and confirm the state advances to Payment accepted.

4. Server, PHP and Callback Timeouts

Hosted gateways such as Stripe and PayPal confirm payment by sending a server-to-server notification to your store. If your server blocks, delays or times out that request, the payment is real, but PrestaShop never hears about it, and the order stays in a pending state.

This cause is harder to spot because the customer sees a successful payment and the gateway dashboard agrees, yet the order never moves. Identify it by checking the gateway's notification or webhook log for failed deliveries to your domain. Fix it by allowing the gateway's IP addresses through your firewall, raising the PHP execution time for the validation controller, and confirming your PHP version is still supported by your PrestaShop release.

  • Confirm the webhook shows a 200 response, not a 403, 404 or 500.
  • Whitelist the gateway's notification IPs in the server firewall.
  • Check that the callback URL uses HTTPS and resolves from outside your network.
  • Verify your PHP version matches the supported range for your PrestaShop version.

Cleaning Up Orders That Already Failed

Once you have stopped new failed orders appearing, the backlog remains. A store that has been running for months can hold a large number of orders sitting in a payment error state, and each one is quietly distorting your stock levels and your sales figures.

The instinct is to delete them. Resist it: deleting an order removes its stock movements with it, so you lose the audit trail you need if a customer later disputes a charge or a stock count looks wrong.

Cancel Rather Than Delete

Cancelling keeps the order record and its history intact while marking it as no longer live. PrestaShop gives you a bulk action on the Orders list where you can select several orders and change their status in one go. Set them to the appropriate cancelled or error state instead of removing them.

Where Stock Goes When You Cancel

Whether cancelling returns stock to the shelf depends on your order settings and on how the order was placed. Check the Stock Movements tab on a single order to see exactly what was deducted and when.

  • If the order was validated with stock decremented, cancelling with the correct settings restores that quantity.
  • If stock was never taken, cancelling changes nothing on the inventory side, which is fine.
  • If you delete instead, those movements vanish from the ledger and any stock correction you make later becomes guesswork.

Keeping Failed Orders Out of Your Reports

Revenue dashboards usually count every order that reached a validated state, so stale failed orders inflate your totals. Set up a dedicated error or cancelled status and filter it out of your reporting views so the numbers you act on reflect real money.

If you sell event tickets or time-limited products, that same discipline matters. Our PrestaShop Events Module lets you manage events, tickets and linked products from one place, which makes it much easier to spot a ticket order that never really paid, whether you sell seats online or use the module as event calendar software for PrestaShop with a slider for upcoming dates.

When Is A Duplicate Order A Separate Problem?

A failed order is one record sitting in the wrong state. A duplicate order is two records for the same purchase, and the two need different fixes. Usually the customer hit Pay, saw nothing happen, and clicked again. Or the payment module called validateOrder() twice because a retry fired before the first response came back.

Open both orders in the back office and compare the cart ID stored on each one. Every order row carries the ID of the cart it came from, so two orders sharing the same cart ID are the same basket submitted twice. Different cart IDs mean the customer genuinely rebuilt the basket, which is a different scenario entirely.

Payment callbacks are the other common source. If your module handles a webhook or an IPN from a provider such as Stripe or PayPal, the same notification can arrive more than once. Without an idempotency check (storing the transaction reference and skipping it on a repeat), each delivery creates another order. Check the transaction ID field on both records: an identical reference across two orders is the giveaway.

  • Same cart ID and different transaction IDs: the customer paid twice, and one order needs refunding.
  • Same cart ID and identical transaction IDs: a webhook replay, so cancel the second record and keep the audit note.
  • Different cart IDs, same customer, minutes apart: a retry after a failure, not a true duplicate.

Store owners selling timed bookings hit this most, because a customer buying seats on the same date will legitimately place two orders. The Prestashop Events Module ($49.99) keeps each booking tied to its own event and ticket record, which makes a replayed submission easier to spot against the ticket stock.

Step-by-Step Diagnosis Process

Work through these steps in order when the quick fixes have not settled the problem. Each step narrows the cause before you reach for code.

  1. Record the exact order state and the order reference of one affected order.
  2. Find that transaction in the gateway dashboard. A decline or missing transaction confirms a genuine failed payment.
  3. Open the order's state history and note whether any payment entry was ever recorded.
  4. Check the gateway's notification or webhook log for a failed delivery to your domain.
  5. Confirm the payment module's callback URL matches your live store address over HTTPS.
  6. Reproduce the failure on a staging copy with cache and non-essential modules disabled.
  7. Re-enable modules and cache one layer at a time until the failed order reappears.
  8. Once identified, fix the module, the state mapping or the server rule, then run a declined test payment to confirm no new order is created.

Advanced Troubleshooting

When the standard checks come up clean, these techniques surface the detail the back office hides.

  • Debug Mode. Switch PrestaShop into debug mode from Advanced Parameters, then Performance, so errors are shown instead of hidden. Turn it off again once you have your answer; never leave it on for customers.
  • Error Logs. Read the PrestaShop log files for the exact moment of the callback. A fatal error there explains a payment that never settled.
  • Server Logs. Your web server's access and error logs show whether the gateway notification even reached the store, and with what response code.
  • Browser Console. On the confirmation step, a failed script or blocked request in the console shows a checkout that never finished loading.
  • Gateway webhook log. Stripe and PayPal both keep a delivery history with response codes and retries, which is the clearest proof of where the confirmation stopped.
  • Conflict testing. On staging, disable modules and switch to the default theme to rule out a checkout override.

For more on managing the modules involved, see the Prestashop Plugins documentation and module listings, which flag compatibility with recent PrestaShop versions.

How To Prevent This Problem

Prevention comes down to controlling what changes on your store and testing the payment flow after every change.

  • Re-check The Order State Mapping. After any update, confirm that the "Payment accepted" state is still tied to the correct status and that failed or pending states are still set to something other than an order.
  • Test callbacks in sandbox first. Run a full transaction, a declined card, and a cancelled payment in the gateway's test mode before going live. Each should leave the cart or a clearly non-valid order, not a confirmed one.
  • Keep a cron for stale carts. Schedule a regular clean-up task so abandoned or orphaned carts do not sit indefinitely, obscuring the real order picture.
  • Monitor logs after deployment. Watch the PrestaShop logs and gateway callback logs for the first 24 hours after a change, rather than waiting for a customer complaint.
  • Alert on "Payment error" spikes. A sudden rise in failed orders is the earliest signal that a gateway or module change has broken the flow.

Treat this checklist as a release gate, not an optional extra. A few minutes of sandbox testing after an update is far cheaper than reconciling a week of phantom orders.

How To Prevent Recurrence: A PrestaShop Payments Checklist

Once a failed payment order has been cleaned up and the cause fixed, the goal shifts to making sure it does not come back after the next module update. Payment behaviour rarely breaks on its own; it breaks when something underneath it changes and no one re-tests the flow.

Run this short checklist every time you update a payment module, switch gateway, or change how order states are mapped.

  • Confirm the gateway's notification IP ranges are still allowed by your firewall after any hosting change.
  • Keep one trusted test card per gateway so every retest uses a known decline or success.
  • Document which order state each failure maps to, so a future update can be checked against it.

These resources genuinely help you diagnose and prevent stuck payment states, rather than paper over them.

  • Your payment gateway's own dashboard and webhook log (Stripe, PayPal and most hosted gateways provide both) is the first place to prove whether a payment happened.
  • PrestaShop's built-in debug mode and log files show the errors the front end hides.
  • The PrestaShop Addons listings on PrestaShop Plugins tell you whether a module is kept current with your platform version.
  • If you sell tickets or events alongside products, the PrestaShop Events Module keeps each booking tied to its own event and ticket record, which makes confirming real sales against failed attempts far easier.

Final Verdict

PrestaShop failed orders are almost never a broken store. They are an order written at the right moment and left in the wrong state, and the fix is to trace that state back to the module, callback or server rule that failed to advance it. Work from the simplest check upward: read the state, confirm the gateway, then test the callback.

When you sell tickets alongside products, tying each booking to a confirmed order makes the whole flow easier to trust. That is exactly what the Prestashop Events Module | Create & Sell Tickets For Events Online does for $49.99, keeping events, tickets and links to products in one place so a failed payment never looks like a real sale.

Frequently Asked Questions

Why does PrestaShop create an order when the payment fails?+–
Because the order is written when the payment module callsvalidateOrder(), before the gateway confirms. If the payment then declines or the confirmation never returns, the order record stays in an intermediate state.
Are PrestaShop failed orders real orders I should worry about?+
They are real database records but not real sales. No money was collected, so they should be moved to an error or cancelled state rather than treated as revenue.
Should I delete failed orders or cancel them?+
Cancel them. Deleting removes the order along with its stock movements and history, while cancelling keeps the audit trail and restores stock where the settings allow.
Why does the order sit in Awaiting payment after a successful charge?+
The gateway's server-to-server notification probably never reached your store. Check the webhook log for a failed delivery, confirm the URL uses HTTPS, and allow the gateway's IPs through your firewall.
How do I stop duplicate orders for one purchase?+
Compare the cart ID and transaction ID on both records. An identical transaction ID points to a replayed webhook, which an idempotency check in the module prevents.
Does a failed order still reduce my stock?+
It can, depending on your settings in Shop Parameters then Order Settings. Check the Stock Movements tab on the order, then restock if the quantity was deducted.
Will updating the payment module fix this?+
Often, yes. Outdated connectors can call the order routine on an error response, so updating through the Module Manager removes a common cause.
How can I test whether the problem is fixed?+
Place a real test order with a card you know will decline, then confirm that no new order appears in the Orders list.