2 Fatal Error
-
FIRST ERROR:
Uncaught Exception: Invalid payment token. in …wp-content/plugins/woocommerce/includes/data-stores/class-wc-payment-token-data-store.php:174
Stack trace:
#0 …wp-content/plugins/woocommerce/includes/class-wc-data-store.php(159): WC_Payment_Token_Data_Store->read()
#1 …wp-content/plugins/woocommerce/includes/abstracts/abstract-wc-payment-token.php(79): WC_Data_Store->read()
#2 …wp-content/plugins/woocommerce/includes/class-wc-payment-tokens.php(172): WC_Payment_Token->__construct()
#3 …wp-content/plugins/woocommerce/includes/class-wc-payment-tokens.php(50): WC_Payment_Tokens::get()
SECOND ERROR:
Uncaught Error: Class “SkyVerge\WooCommerce\PluginFramework\v5_15_10\Admin\Notes_Helper” not found in …wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php:825
Stack trace:
#0 …wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php(606): SkyVerge\WooCommerce\PluginFramework\v5_15_10\SV_WC_Payment_Gateway_Plugin->add_gateway_not_configured_notices()
#1 …/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/includes/WC_Braintree.php(785): SkyVerge\WooCommerce\PluginFramework\v5_15_10\SV_WC_Payment_Gateway_Plugin->add_delayed_admin_notices()
#2 …/wp-includes/class-wp-hook.php(341): WC_Braintree\WC_Braintree->add_delayed_admin_notices()
#3 …wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters()
-
This is PHP 8.4 FPM on pure NGINX on Ubuntu, running multisite
Hi @elkrat,
Thanks for sharing these detailed error logs, I can see you are running into two separate fatal errors on your setup, and I’d like to help you narrow this down and get things working smoothly.
From what you shared, the first error around the invalid payment token typically points to stored payment tokens that may no longer be valid or are incompatible with the current environment. This can sometimes happen after updates or environment changes. The second error indicates that a required class from the SkyVerge framework is not being found, which usually suggests a plugin conflict, incomplete update, or a version mismatch involving the Braintree plugin.
Since you are running PHP 8.4, it would be worth testing on PHP 8.3 to help rule out any edge compatibility issues with the plugin stack.
It would also help to check the following
– Ensure both WooCommerce and the Braintree for WooCommerce plugin are updated to their latest versions
– Temporarily deactivate and reactivate the Braintree plugin to make sure all files are properly loaded
– Test for plugin conflicts by disabling other plugins except WooCommerce and Braintree
– Clear any cached payment tokens by removing saved payment methods and testing againYou can follow this guide for conflict testing https://woocommerce.com/document/how-to-test-for-conflicts/
If the issue continues, please share your System Status Report via https://pastebin.com or https://gist.github.com so we can take a closer look at your environment setup.
Looking forward to your update so we can continue from there.
I’m disregarding the second error about the missing class. It has not repeated.
The first error about the missing token has happened again. These payment attempts are from Woo Subscriptions. I’ve had carding attacks and it’s possible I’ve deleted a fake user, or had a fake user create an erroneous token during the subscription signup process.
I am adding a new exception under yours, to see if it even returns a token ID
throw new Exception( __( 'Invalid payment token.', 'woocommerce' ) );throw new Exception( __( 'Invalid token ID:'.$token->get_id(), 'woocommerce' ) );If this doesn’t work, I will hook earlier in the subscription renewal process and log the subscription and user ID there. That will give me a timestamp match to find the bad user.
Hi there!
Thank you for the detailed update and for sharing the steps you’re taking to debug this.
Adding additional logging around the exception to confirm whether a token ID is returned is a good approach and should help identify exactly where the failure occurs during the renewal process.
Since the error indicates a missing or invalid payment token, the most reliable next step is to identify which subscription renewal is triggering the error. Hooking earlier into the subscription renewal process and logging the subscription ID, user ID, and timestamp is a solid method to correlate the failed renewal attempt with a specific record.
I would also suggest checking the
wp_woocommerce_payment_tokensandwp_woocommerce_payment_tokenmetatables for tokens that reference non-existent user IDs or subscriptions, and cleaning those up if found.If your additional exception outputs a specific token ID, you can then:
- Look up that token directly in the database to confirm whether it is orphaned or malformed.
- Remove only that token (or reassign it if appropriate), and then retry the renewal to confirm whether the fatal error is resolved.
Let us know what you find.
The fatal error seems to take place when my clients are adding new Payment Methods to their accounts. They have not complained that the cards are failing to save, so this may be an error that few people notice. Here is the log and you can see in the stack trace what’s going on:
Uncaught Exception: Invalid payment token. in /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/data-stores/class-wc-payment-token-data-store.php:174
Stack trace:
#0 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/class-wc-data-store.php(159): WC_Payment_Token_Data_Store->read()
#1 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/abstracts/abstract-wc-payment-token.php(79): WC_Data_Store->read()
#2 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/class-wc-payment-tokens.php(172): WC_Payment_Token->__construct()
#3 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/class-wc-payment-tokens.php(50): WC_Payment_Tokens::get()
#4 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-token.php(632): WC_Payment_Tokens::get_tokens()
#5 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-token.php(739): SkyVerge\WooCommerce\PluginFramework\v6_0_1\SV_WC_Payment_Gateway_Payment_Token->get_woocommerce_payment_token()
#6 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php(853): SkyVerge\WooCommerce\PluginFramework\v6_0_1\SV_WC_Payment_Gateway_Payment_Token->save()
#7 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/includes/WC_Braintree_Payment_Method_Handler.php(93): SkyVerge\WooCommerce\PluginFramework\v6_0_1\SV_WC_Payment_Gateway_Payment_Tokens_Handler->update_tokens()
#8 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php(741): WC_Braintree\WC_Braintree_Payment_Method_Handler->update_tokens()
#9 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-payment-form.php(160): SkyVerge\WooCommerce\PluginFramework\v6_0_1\SV_WC_Payment_Gateway_Payment_Tokens_Handler->get_tokens()
#10 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/includes/Payment_Forms/WC_Braintree_Payment_Form.php(87): SkyVerge\WooCommerce\PluginFramework\v6_0_1\SV_WC_Payment_Gateway_Payment_Form->get_tokens()
#11 /usr/share/nginx/mysite/wp-content/plugins/woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php(893): WC_Braintree\Payment_Forms\WC_Braintree_Payment_Form->render()
#12 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/templates/myaccount/form-add-payment-method.php(40): SkyVerge\WooCommerce\PluginFramework\v6_0_1\SV_WC_Payment_Gateway->payment_fields()
#13 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/wc-core-functions.php(350): include('...')
#14 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php(416): wc_get_template()
#15 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/wc-template-functions.php(3738): WC_Shortcode_My_Account::add_payment_method()
#16 /usr/share/nginx/mysite/wp-includes/class-wp-hook.php(341): woocommerce_account_add_payment_method()
#17 /usr/share/nginx/mysite/wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters()
#18 /usr/share/nginx/mysite/wp-includes/plugin.php(522): WP_Hook->do_action()
#19 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/wc-template-functions.php(3617): do_action()
#20 /usr/share/nginx/mysite/wp-includes/class-wp-hook.php(341): woocommerce_account_content()
#21 /usr/share/nginx/mysite/wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters()
#22 /usr/share/nginx/mysite/wp-includes/plugin.php(522): WP_Hook->do_action()
#23 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/templates/myaccount/my-account.php(34): do_action()
#24 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/wc-core-functions.php(350): include('...')
#25 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php(121): wc_get_template()
#26 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php(57): WC_Shortcode_My_Account::my_account()
#27 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/class-wc-shortcodes.php(75): WC_Shortcode_My_Account::output()
#28 /usr/share/nginx/mysite/wp-content/plugins/woocommerce/includes/class-wc-shortcodes.php(118): WC_Shortcodes::shortcode_wrapper()
#29 /usr/share/nginx/mysite/wp-includes/shortcodes.php(434): WC_Shortcodes::my_account()
#30 [internal function]: do_shortcode_tag()
#31 /usr/share/nginx/mysite/wp-includes/shortcodes.php(273): preg_replace_callback()
#32 /usr/share/nginx/mysite/wp-includes/class-wp-hook.php(341): do_shortcode()
#33 /usr/share/nginx/mysite/wp-includes/plugin.php(205): WP_Hook->apply_filters()
#34 /usr/share/nginx/mysite/wp-includes/post-template.php(256): apply_filters()
#35 /usr/share/nginx/mysite/wp-content/themes/Divi/page.php(46): the_content()
#36 /usr/share/nginx/mysite/wp-includes/template-loader.php(132): include('...')
#37 /usr/share/nginx/mysite/wp-blog-header.php(19): require_once('...')
#38 /usr/share/nginx/mysite/index.php(17): require('...')
#39 {main}Hi there!
Thank you for sharing the more detalis about the issue. This error means:
- WooCommerce tried to load a saved payment method
- But the token is invalid, missing, or corrupted
- So it throws an exception when trying to read it
I’ve tried to replicate the issue on my end by adding a payment method while logged in as a customer, but I wasn’t able to reproduce it everything appears to be working fine here.
To assist you further, could you please confirm which payment method you’re trying to add when this error is triggered? For example, credit card via Braintree, PayPal via Braintree, or another payment method provided by a third-party plugin.
Also, please share your System Status Report via https://pastebin.com or https://gist.github.com so we can take a closer look at your environment setup.
The only two payment methods available on my system are PP by Braintree and CC by Braintree. I could not reproduce the problem – card addition was successful. And I can’t test Paypal because my Paypal account is the actual account where payments go.
I even stressed the Add Payment Method functionality by adding both a new card and a duplicate card. It correctly reported messages from the Braintree portal and no error was generated in the logs. I guess I’ll just keep an eye on it. Thanks for your time.
Hi there,
Thank you for the detailed update and for taking the time to thoroughly test this on your end that’s really helpful.
It’s great to hear that you were unable to reproduce the issue and that adding both new and duplicate cards is working as expected, with proper responses coming from Braintree and no errors in the logs. That generally indicates things are functioning correctly at the moment.
I understand the limitation with testing PayPal due to it being your live account, and that’s completely fine.
At this stage, keeping an eye on it is a sensible approach. If the issue does come up again, I’d recommend noting down the exact steps, any error messages shown, and checking the logs at that time that will help us narrow things down much more effectively.
If anything changes or you notice the issue recurring, feel free to reach out and we’ll be happy to take a closer look.
Similar fatal error issue as OP after 3.10.0 update —
SkyVerge\…\Admin\Notes_Helperclass not found in adminPlugin: WooCommerce PayPal Powered by Braintree
Version that triggered the fatal: 3.10.0
Last known-good version: 3.8.0 (rolled back; site stable on this version)Environment:
- WordPress 6.9.4
- WooCommerce 10.7.0
- PHP 8.2
- PayPal-Braintree update triggered at 2026-05-13 09:35:31 EDT (13:35:31 UTC); first fatal at 13:35:33 UTC — same minute, same admin pageload, no other plugin changes in between.
What broke: Immediately after 3.10.0 installed, the WordPress admin (specifically
/wp-admin/edit.php?post_type=shop_orderand the post editor) returned HTTP 500. PHP fatal:Uncaught Error: Class "SkyVerge\WooCommerce\PluginFramework\v5_15_10\Admin\Notes_Helper" not found in .../woocommerce-gateway-paypal-powered-by-braintree/vendor/skyverge/wc-plugin-framework/woocommerce/payment-gateway/class-sv-wc-payment-gateway-plugin.php on line 825Stack trace points to
SV_WC_Payment_Gateway_Plugin::add_gateway_not_configured_notices()calling intoNotes_Helper. The class is referenced in the bundled SkyVerge framework (v5_15_10) but does not appear to exist in the vendor tree shipped with 3.10.0 — at least not at a path the autoloader resolves.Reverting to 3.8.0 (downloaded from
https://downloads.wp.xz.cn/plugin/woocommerce-gateway-paypal-powered-by-braintree.3.8.0.zip) eliminates the fatal entirely. No other plugins or theme files changed.Reproducer: With WooCommerce 10.7.0 active on PHP 8.2, install PayPal-Braintree 3.10.0 and visit any admin page that triggers
add_delayed_admin_notices(Orders list, product editor). The fatal fires at the admin-footer hook, after the page HTML has already started rendering — so the user sees a partial admin page followed by a critical-error response.Likely cause: v3.10.0 ships an outdated copy of the bundled SkyVerge plugin framework (
v5_15_10) that referencesAdmin\Notes_Helperinadd_gateway_not_configured_notices()but does not include the class file invendor/skyverge/wc-plugin-framework/woocommerce/admin/. Either the class was removed between framework releases without removing the call site, or the autoloader manifest in the 3.10.0 release is incomplete.Happy to provide the full debug.log excerpt or test against any patch you’d like to validate.
Reverted to previous release without issue.Hi @billgaffney
I understand that you have a somewhat similar problem.
However, per forum best practices shown here, it is advised that you create a new thread so that we can address your issue(s) separately.
You can create a new thread here: https://ww.wp.xz.cn/support/plugin/woocommerce/#new-topic-0 and make sure to include as much information as you can.
Thanks for understanding!
Okay, these errors are from carding attacks. I hooked into
before_woocommerce_add_payment_method()and logged the user ids.So now I’m recording each IP address that attempts to add 3 payment methods a day, without regard to the user id, and banning them for 24 hrs via direct addition to the WordFence block table. I’m also recording that IP in a second table so that if they re-offend, it gets banned for 90 days. Here’s what I’m doing:
add_action( 'before_woocommerce_add_payment_method', 'limit_payment_method_additions' );
function limit_payment_method_additions(){
global $wpdb;
$additions_table = 'daily_pay_method_additionss';
$recid_table = 'pay_method_addition_recidivists';
$ip = $_SERVER['REMOTE_ADDR'];
$until = 'not yet banned';
$daily_row = $wpdb->get_results("SELECT * FROM $additions_table WHERE ip = '$ip'");
$count = $daily_row ? $daily_row->count : false;
if ( ! $count){
$wpdb->insert(
$additions_table,
array(
'ip' => $ip,
'count' => 1,
),
array('%s, %d'),
);
} else if ($count < 3){
// You're on thin ice, buddy.
$count ++;
$wpdb->update(
$additions_table,
array(
'ip' => $ip,
'count' => $count,
),
array(
'ip' => $ip
)
);
} else {
// HOIST EM
// if they're a recidivist, we ban them for a month
$recidivist = $wpdb->get_results("SELECT * FROM $recid_table WHERE ip = '$ip'");
$until = $recidivist ? time() + 7776000 : time() + 86400;
$network_ip = inet6_aton($ip);
$block_reason = $recidivist ? 'Two time payment method offender' :'Exceeded 3 payment method additions in one day';
$data = array(
'type' => 1,
'blockedTime' => time(),
'expiration' => $until, // 0 means permanent block
'IP' => $network_ip,
'lastAttempt' => 0,
'blockedHits' => 0,
'reason' => $block_reason,
'parameters' => serialize(array()),
);
$wpdb->insert('wp_wfBlocks7', $data);
if ( ! $recidivist){ // you will be next time!
$wpdb->insert(
$recid_table,
array(
'ip' => $ip,
),
array('%s'),
);
}
// this table gets truncated each night by cron anyway
$wpdb->delete($additions_table, array('id' => $daily_row->id), array('%d'));
}
$user_id = get_current_user_id();
$user_blogs = '';
if ( ! $user_id){
$user_id = 'User ID False';
} else {
$user_blogs = get_blogs_of_user($user_id);
}
$caller = 'limit_payment_method_additions()';
$label = 'Who is this user?';
$was_recidivist = $recidivist ? 'true':'false';
$payload = serialize(array(
'$user_id' => $user_id,
'ip address' => ip,
'count' => $count,
'was a recidivist' => $was_recidivist,
'ban end time' => $until,
'$user_blogs' => $user_blogs,
));
custom_log($caller, $label, $payload);
}Hi @elkrat,
Great detective work! Identifying carding attacks as the root cause and building your own IP-based rate limiting is a solid approach. While custom code falls outside what we support here, a few things in your implementation are worth flagging as they could cause silent failures:
1. SQL injection risk:
$_SERVER['REMOTE_ADDR']is used directly in raw query strings. If your server sits behind a proxy forwardingX-Forwarded-For, this could be spoofed. Always wrap raw queries in$wpdb->prepare().2.
$wpdb->get_results()returns an array, not an object$daily_row->countand$daily_row->idwill evaluate tonull. Use$daily_row[0]->countand$daily_row[0]->id, or switch to$wpdb->get_row()since you’re only expecting one result per IP.3.
inet6_aton()is a MySQL function, not PHP. This will cause a fatal error. Use PHP’sinet_pton($ip)instead to convert the IP to the binary format Wordfence’swfBlocks7table expects.4. Typo in payload —
'ip address' => ipshould be'ip address' => $ip.Regarding the original Braintree fatal errors, since those are tied to orphaned tokens from the carding attacks and involve your specific Braintree setup, our Happiness Engineers would be best placed to help you investigate further and ensure nothing is lingering. Could you please open a support ticket here and reference this forum thread? That way they’ll have the full context of everything discussed so far and can dig into your Braintree configuration directly.
Hope that helps.
Thanks for the corrections! I just whipped that up and didn’t test it. I used sanitize_text_field() on the ip address and changed to $wpdb->get_row(). I will open a ticket soon.
Hi there!
Thanks for the update, and I’m glad those observations were helpful.
It sounds like you’ve already made some good improvements to the implementation. Since the remaining concerns relate to your specific Braintree setup and the effects of the carding attacks, opening a support ticket is the best next step.
When you do, please include a link to this thread along with any relevant error logs or recent examples you can gather. That will help the team review the situation more efficiently.
We’ll be happy to take a closer look there.
You must be logged in to reply to this topic.