Extension: Payment Failed Email
-
Extension Name: ext.magento2.cleverzoeger.payment-failed-email (CleverZoeger_PaymentFailedEmail)
-
Magento Compatibility: 2.4.6, 2.4.7, 2.4.8, 2.4.9 (PHP 8.1, 8.2, 8.3, 8.4)
Magento core sends the "Payment Failed" email (checkout/payment_failed/*) unconditionally —
unlike the New Order, Invoice, Shipment and Credit Memo emails, it has no Enabled toggle in
Stores > Configuration > Sales > Checkout > Payment Failed Emails. This extension adds that
missing toggle.
Features
-
Adds an
Enabledfield (default: Yes, matches previous behavior) toStores > Configuration > Sales > Checkout > Payment Failed Emails. -
When disabled, the Payment Failed email is not sent; all other Payment Failed Email settings (sender, receiver, template, copy to, copy method) are hidden via
dependsuntil re-enabled. -
Store-view scoped, like the other sales email
Enabledsettings.
Background: why this extension exists
While reviewing var/log/exception.log on production, we found repeated, bursty
main.CRITICAL entries (multiple hits within the same minute, recurring across separate days)
for:
Magento\Framework\Exception\NoSuchEntityException: Keine Eintrag mit cartId = 0
Every one of these traces goes through the same call path:
Magento\Paypal\Controller\Transparent\Response->execute()
-> Magento\Sales\Model\Service\PaymentFailuresService->handle()
-> Magento\Quote\Model\QuoteRepository->get() [throws NoSuchEntityException, uncaught]
Magento\Paypal\Controller\Transparent\Response (PayPal Payflow "Transparent Redirect") is a
HttpPostActionInterface controller that explicitly disables CSRF validation
(validateForCsrf() returns true unconditionally, createCsrfValidationException() returns
null), so it accepts POST requests without a referrer/form-key check. On any
LocalizedException while processing the posted payment response, it calls:
$this->paymentFailures->handle((int) $this->sessionTransparent->getQuoteId(), $parameters['error_msg']);
getQuoteId() comes from the transparent-redirect session, not from request input. When this
controller is called directly/out of the normal checkout flow — as happened here, in bursts
consistent with automated scanning rather than real checkout attempts — no transparent-redirect
session exists yet, so the quote ID is 0. PaymentFailuresService::handle() then does
$this→cartRepository→get(0), which throws NoSuchEntityException. Magento core does not catch
this, so every such request produces an uncaught, logged CRITICAL exception. Across the observed
period (2026-09-11 to 2026-09-15) this alone accounted for 189 log entries and contributed to
exception.log growing to roughly 99.5 MB.
Because Magento core has no Enabled toggle for Payment Failed Emails, there was also no
supported way to mute or rate-limit the resulting noise (log growth, and on any request that did
resolve to a real, payment-less quote, an actual "Payment Failed" email) without patching core.
This extension’s config toggle lets this be switched off per store view without a core patch or a
code deployment.
Screenshots
Backend
Enabled field
No the Payment Failed Email is suppressed and the remaining settings are hiddenFrontend
The extension has no storefront output of its own; what it switches on and off is the transactional Payment Failed email.
YesThis documentation is brought to you by the clever+zöger GmbH. We are developing Magento projects since 2008 and since 2020 we are Adobe Solution partner. If you have any issues, don’t hesitate to contact us support@clever-zoeger.de.