Home › Toolset Professional Support › [Fixed in next Release] Fatal error: Uncaught ValueError
This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.
Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
- | 7:00 – 14:00 | 7:00 – 14:00 | 7:00 – 14:00 | 7:00 – 14:00 | 7:00 – 14:00 | - |
- | 15:00 – 16:00 | 15:00 – 16:00 | 15:00 – 16:00 | 15:00 – 16:00 | 15:00 – 16:00 | - |
Supporter timezone: Europe/London (GMT+00:00)
This topic contains 9 replies, has 2 voices.
Last updated by UNC Digital Services 2 months ago.
Assisted by: Nigel.
I am trying to: upgrade to php 8
Link to a page where the issue can be seen:
hidden link
I expected to see:
hidden link
Instead, I got:
We are trying to update to php 8.1, but im seeing this error with php 8.2 and 8.3
Fatal error: Uncaught ValueError: Missing format specifier at end of string in /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php:200 Stack trace: #0 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php(200): sprintf('Add New %', 'Issue/Fix') #1 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php(104): wpcf_custom_types_register('issues-fixes', Array) #2 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/functions.php(117): wpcf_custom_types_init() #3 /code/web/wp-includes/class-wp-hook.php(324): wpcf_init_custom_types_taxonomies('') #4 /code/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #5 /code/web/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #6 /code/web/wp-settings.php(700): do_action('init') #7 /code/web/wp-config.php(280): require_once('/code/web/wp-se...') #8 /code/web/wp-load.php(50): require_once('/code/web/wp-co...') #9 /code/web/wp-blog-header.php(13): require_once('/code/web/wp-lo...') #10 /code/web/index.php(17): require('/code/web/wp-bl...') #11 {main} thrown in /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php on line 200
I also cannot get into the backend to get the debug info
another site shows similar
Fatal error: Uncaught ValueError: Unknown format specifier "p" in /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php:209 Stack trace: #0 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php(209): sprintf('Search %p', 'Marketing Updat...') #1 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php(104): wpcf_custom_types_register('marketing-updat...', Array) #2 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/functions.php(117): wpcf_custom_types_init() #3 /code/web/wp-includes/class-wp-hook.php(324): wpcf_init_custom_types_taxonomies('') #4 /code/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #5 /code/web/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #6 /code/web/wp-settings.php(700): do_action('init') #7 /code/web/wp-config.php(280): require_once('/code/web/wp-se...') #8 /code/web/wp-load.php(50): require_once('/code/web/wp-co...') #9 /code/web/wp-blog-header.php(13): require_once('/code/web/wp-lo...') #10 /code/web/index.php(17): require('/code/web/wp-bl...') #11 {main} thrown in /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php on line 209
Languages: English (English ) Spanish (Español )
Timezone: Europe/London (GMT+00:00)
Hi there
Could you please review the settings for your custom post type "Issues/Fixes" and check the Labels section (see screenshot of my test site).
The error message suggests to me that you may have changed "Add New %s" to "Add New %".
Similarly, on the other site, check the label for Search items, which is normally "Search %s", and which it looks like you have changed to an invalid "Search %p".
the sites are terminally white screening. it is probably important to note that:
1. these sites are old.
2. they exist on huge multi-site networks with more than 300 sites per network
3. we have a ton of people using toolset and have been for many many years
4. the only difference between the saml site and the uat site is the saml site is running php 8|
in the saml site, where I dont get a php error, the New Item is New %. that's wrong, but if we have hundreds of sites and the only difference is that this misconfiguration that didn't error out in php 7.4 and fatal errors in php 8.1 it would seem the software needs a try-catch there so that its not a catastrophic failure when we upgrade to php 8.1
its 867 sites that could possibly have an error per post-type label.
is that data serialized in the backend? is there anyway to regen the labels outside of going to 867 sites and checking every CPT label set for an error?
Languages: English (English ) Spanish (Español )
Timezone: Europe/London (GMT+00:00)
When upgrading PHP versions, things that PHP tolerated in older versions (generating a warning, but no error) it stops tolerating (turning the warning into an actual error).
There may have been PHP warnings relating to this before it broke when updating to PHP 8.1.
The labels would have been wrong in the backend UI, so instead of saying "Add New Project" or "Edit Project", for example, it would just say "Add New" and "Edit".
Unfortunately I don't see an easy way to fix this across hundreds of sites, unless all of the sites have the same problem with the same custom post types.
In that case it might be possible to write a simple script to update the settings for those post types, but it would still imply running that code on each site (possibly by adding the code as a drop-in plugin, or perhaps using the WP CLI if that were an option).
The details of the options for each post type are stored in wp_options in an option with option_name = 'wpcf-post-types'.
The data is serialized, but if you get the option value via get_option it will automatically unserialize it into an array, which would look something like this (for a Things post type from my own test site):
Array ( [thing] => Array ( [labels] => Array ( [name] => Things [singular_name] => Thing [add_new] => Add New [add_new_item] => Add New %s [edit_item] => Edit %s [new_item] => New %s [view_item] => View %s [search_items] => Search %s [not_found] => No %s found [not_found_in_trash] => No %s found in Trash [parent_item_colon] => Parent text [all_items] => All items [enter_title_here] => Enter title here ) [slug] => thing [description] => [public] => public [capabilities] => Array ( ) [menu_position] => [menu_icon] => [taxonomies] => Array ( ) [supports] => Array ( [title] => 1 [editor] => 1 [author] => 1 [thumbnail] => 1 ) [rewrite] => Array ( [enabled] => 1 [custom] => normal [slug] => [with_front] => 1 [feeds] => 1 [pages] => 1 ) [has_archive] => 1 [show_ui] => 1 [show_in_menu] => 1 [show_in_menu_page] => [publicly_queryable] => 1 [exclude_from_search] => [hierarchical] => [query_var_enabled] => 1 [query_var] => [can_export] => 1 [show_in_rest] => 1 [rest_base] => [show_in_nav_menus] => 1 [register_meta_box_cb] => [permalink_epmask] => EP_PERMALINK [update] => [_builtin] => [_toolset_edit_last] => 1724943848 [_wpcf_author_id] => 1 [wpcf-post-type] => thing [icon] => awards [editor] => block [custom-field-group] => Array ( ) [has_archive_slug] => [is_repeating_field_group] => [is_intermediary_post_type] => [hidden_related_content_metaboxes] => Array ( ) ) )
right, but that still means if a user goes into a site and edits the labels for a cpt wrong, the entire site is unusable. and this only happens in php 8.1+ you need some error checking there in the plugin to say: "no bad user" when they put a bad value in there. or this plugin is really not php 8.1 compatible
PS Im not the user, I'm the dev. adding a bad config to another site on the same dev network makes the whole site error like
Fatal error: Uncaught ValueError: Missing format specifier at end of string in /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php:200 Stack trace: #0 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php(200): sprintf('Add New %', 'Person') #1 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php(104): wpcf_custom_types_register('people', Array) #2 /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/functions.php(117): wpcf_custom_types_init() #3 /code/web/wp-includes/class-wp-hook.php(324): wpcf_init_custom_types_taxonomies('') #4 /code/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #5 /code/web/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #6 /code/web/wp-settings.php(700): do_action('init') #7 /code/web/wp-config.php(280): require_once('/code/web/wp-se...') #8 /code/web/wp-load.php(50): require_once('/code/web/wp-co...') #9 /code/web/wp-admin/admin.php(34): require_once('/code/web/wp-lo...') #10 {main} thrown in /code/web/wp-content/plugins/types/vendor/toolset/types/embedded/includes/custom-types.php on line 200
that bit of code in types/vendor/toolset/types/embedded/includes/custom-types.php can fail a bit more gracefully with
switch ($label_key) {
case 'add_new_item':
case 'edit_item':
case 'new_item':
case 'view_item':
case 'parent_item_colon':
try {
$data['labels'][$label_key] = sprintf($label, $data['labels']['singular_name']);
} catch (ValueError $e) {
error_log('Caught exception: ' . $e->getMessage() );
}
break;
case 'search_items':
case 'all_items':
case 'not_found':
case 'not_found_in_trash':
case 'menu_name':
try {
$data['labels'][$label_key] = sprintf($label, $data['labels']['name']);
} catch (ValueError $e) {
error_log('Caught exception: ' . $e->getMessage() );
}
break;
}
at the end maybe if the $data['labels'][$label_key] is not set, set it to things
Languages: English (English ) Spanish (Español )
Timezone: Europe/London (GMT+00:00)
I agree that the best solution is to update the Types code base to prevent it throwing fatal errors in a scenario where a post type label "misuses" the % sign (I recognise that there is nothing in our UI to warn users to be careful with the % sign).
I've escalated this to the developers, and requested that an update to prevent such errors be included in the next Types release.
In which case you would be able to roll out the Types update to your network of sites, and then update them to PHP 8.1.
I'll keep you updated of any progress in the ticket.
Languages: English (English ) Spanish (Español )
Timezone: Europe/London (GMT+00:00)
I'm pleased to say that the developers jumped straight on this and have fixed this in development, such that it will be included in the next Types release.
I don't have a timetable for when that is, but it does mean that if you want to edit the Types plugin code yourself and update yours sites with the modified plugin, you can be confident that the problem won't recur when you install the next Types update.
fantastic! thank you Nigel