Undefined Array Key Fix
August 7, 2025 ยท AI Conversations
"error": {
"type": "Breakdance\Lib\Vendor\Whoops\Exception\ErrorException",
"message": "Undefined array key "key"",
"code": 2,
"file": "/home/cateboxi/public_html/wp-content/plugins/feedoptimise/woocommerce-feedoptimise.php",
"line": 103,
"trace": [
{
"file": "/home/cateboxi/public_html/wp-content/plugins/feedoptimise/woocommerce-feedoptimise.php",
"line": 103,
"function": null,
"class": "Breakdance\Lib\Vendor\Whoops\Exception\ErrorException",
"args": [
"Undefined array key "key""
],
"snippet": {
"98": " if ( isset ( $wp_query->query_vars['woocommerce_feedoptimise'] ) ) {n",
"99": " $_REQUEST['action'] = 'woocommerce_feedoptimise';n",
"100": " $_REQUEST['key'] = $wp_query->query_vars['woocommerce_feedoptimise'];n",
"101": " }n",
"102": "n",
"103": " if ( ( isset ( $_REQUEST['action'] ) && 'woocommerce_feedoptimise_reports' == $_REQUEST['key'] ) ) {n",
"104": "n",
"105": " $secret = esc_attr( get_option('feedoptimise_secret') );n",
"106": "n",
"107": " if($secret && $secret != $_REQUEST['woocommerce_feedoptimise_secret'])n"
},
"startingLine": 98
},
{
"file": "/home/cateboxi/public_html/wp-content/plugins/feedoptimise/woocommerce-feedoptimise.php",
"line": 103,
"function": "handleError",
"class": "Breakdance\Lib\Vendor\Whoops\Run",
"args": [],
"snippet": {
"98": " if ( isset ( $wp_query->query_vars['woocommerce_feedoptimise'] ) ) {n",
"99": " $_REQUEST['action'] = 'woocommerce_feedoptimise';n",
"100": " $_REQUEST['key'] = $wp_query->query_vars['woocommerce_feedoptimise'];n",
"101": " }n",
"102": "n",
"103": " if ( ( isset ( $_REQUEST['action'] ) && 'woocommerce_feedoptimise_reports' == $_REQUEST['key'] ) ) {n",
"104": "n",
"105": " $secret = esc_attr( get_option('feedoptimise_secret') );n",
"106": "n",
"107": " if($secret && $secret != $_REQUEST['woocommerce_feedoptimise_secret'])n"
},
"startingLine": 98
},
{
"file": "/home/cateboxi/public_html/wp-includes/class-wp-hook.php",
"line": 324,
"function": "woocommerce_feedoptimise_includes",
"class": null,
"args": [],
"snippet": {
"319": "n",
"320": "tttt// Avoid the array_slice() if possible.n",
"321": "ttttif ( 0 === $the_['accepted_args'] ) {n",
"322": "ttttt$value = call_user_func( $the_['function'] );n",
"323": "tttt} elseif ( $the_['accepted_args'] >= $num_args ) {n",
"324": "ttttt$value = call_user_func_array( $the_['function'], $args );n",
"325": "tttt} else {n",
"326": "ttttt$value = call_user_func_array( $the_['function'], array_slice( $args, 0, $the_['accepted_args'] ) );n",
"327": "tttt}n",
"328": "ttt}n"
},
"startingLine": 319
},
{
"file": "/home/cateboxi/public_html/wp-includes/class-wp-hook.php",
"line": 348,
"function": "apply_filters",
"class": "WP_Hook",
"args": [],
"snippet": {
"343": "t *n",
"344": "t * @param array $args Parameters to pass to the callback functions.n",
"345": "t */n",
"346": "tpublic function do_action( $args ) {n",
"347": "tt$this->doing_action = true;n",
"348": "tt$this->apply_filters( '', $args );n",
"349": "n",
"350": "tt// If there are recursive calls to the current action, we haven't finished it until we get to the last one.n",
"351": "ttif ( ! $this->nesting_level ) {n",
"352": "ttt$this->doing_action = false;n"
},
"startingLine": 343
},
{
"file": "/home/cateboxi/public_html/wp-includes/plugin.php",
"line": 517,
"function": "do_action",
"class": "WP_Hook",
"args": [],
"snippet": {
"512": "t} elseif ( is_array( $arg[0] ) && 1 === count( $arg[0] ) && isset( $arg[0][0] ) && is_object( $arg[0][0] ) ) {n",
"513": "tt// Backward compatibility for PHP4-style passing of `array( &$this )` as action `$arg`.n",
"514": "tt$arg[0] = $arg[0][0];n",
"515": "t}n",
"516": "n",
"517": "t$wp_filter[ $hook_name ]->do_action( $arg );n",
"518": "n",
"519": "tarray_pop( $wp_current_filter );n",
"520": "}n",
"521": "n"
},
"startingLine": 512
},
{
"file": "/home/cateboxi/public_html/wp-includes/template-loader.php",
"line": 13,
"function": "do_action",
"class": null,
"args": [],
"snippet": {
"8": "t/**n",
"9": "t * Fires before determining which template to load.n",
"10": "t *n",
"11": "t * @since 1.5.0n",
"12": "t */n",
"13": "tdo_action( 'template_redirect' );n",
"14": "}n",
"15": "n",
"16": "/**n",
"17": " * Filters whether to allow 'HEAD' requests to generate content.n"
},
"startingLine": 8
},
{
"file": "/home/cateboxi/public_html/wp-blog-header.php",
"line": 19,
"function": "require_once",
"class": null,
"args": [
"/home/cateboxi/public_html/wp-includes/template-loader.php"
],
"snippet": {
"14": "n",
"15": "t// Set up the WordPress query.n",
"16": "twp();n",
"17": "n",
"18": "t// Load the theme template.n",
"19": "trequire_once ABSPATH . WPINC . '/template-loader.php';n",
"20": "n",
"21": "}n"
},
"startingLine": 14
},
{
"file": "/home/cateboxi/public_html/index.php",
"line": 17,
"function": "require",
"class": null,
"args": [
"/home/cateboxi/public_html/wp-blog-header.php"
],
"snippet": {
"12": " * @var booln",
"13": " */n",
"14": "define( 'WP_USE_THEMES', true );n",
"15": "n",
"16": "/** Loads the WordPress Environment and Template */n",
"17": "require __DIR__ . '/wp-blog-header.php';n"
},
"startingLine": 12
}
]
}
}
Undefined array key "key" in woocommerce-feedoptimise.php on line 103
### ๐ Root Cause
In this code:
if ( ( isset ( $_REQUEST['action'] ) && 'woocommerce_feedoptimise_reports' == $_REQUEST['key'] ) ) {
You're trying to access `$_REQUEST['key']` **without checking if it exists**. If it's not set, PHP throws a warning (or fatal in strict mode).
### ๐ ๏ธ Solution
You must first check if `$_REQUEST['key']` is set before comparing it.
#### โ Fixed Code:
if (
isset($_REQUEST['action'], $_REQUEST['key']) &&
$_REQUEST['action'] === 'woocommerce_feedoptimise' &&
$_REQUEST['key'] === 'woocommerce_feedoptimise_reports'
) {
$secret = esc_attr(get_option('feedoptimise_secret'));
if ($secret && $secret !== ($_REQUEST['woocommerce_feedoptimise_secret'] ?? null)) {
// Handle invalid secret
}
// Continue your report generation logic
}
### โจ Additional Improvements
You may also want to sanitize and validate `$_REQUEST` values using `sanitize_text_field()` or similar to prevent security issues.
Let me know if you want a fallback redirect or message in case the `key` is missing.
—
### ๐ฅ Problem Recap
In your plugin file:
if ( ( isset ( $_REQUEST['action'] ) && 'woocommerce_feedoptimise_reports' == $_REQUEST['key'] ) ) {
This line **assumes** `$_REQUEST['key']` is always present โ which is not guaranteed, hence the error.
—
### โ Recommended Fix (Safe with Breakdance & PHP 8+)
Replace the problematic line **at line 103** with this:
if (
isset($_REQUEST['action'], $_REQUEST['key']) &&
$_REQUEST['action'] === 'woocommerce_feedoptimise' &&
$_REQUEST['key'] === 'woocommerce_feedoptimise_reports'
) {
This uses `isset()` on both keys before accessing them, **avoiding fatal errors** in PHP 8+.
—
### ๐งผ Bonus (Secure & Clean)
If you also want to sanitize incoming values (highly recommended for security):
$action = isset($_REQUEST['action']) ? sanitize_text_field($_REQUEST['action']) : '';
$key = isset($_REQUEST['key']) ? sanitize_text_field($_REQUEST['key']) : '';
if ($action === 'woocommerce_feedoptimise' && $key === 'woocommerce_feedoptimise_reports') {
$secret = esc_attr(get_option('feedoptimise_secret'));
$request_secret = $_REQUEST['woocommerce_feedoptimise_secret'] ?? '';
if ($secret && $secret !== sanitize_text_field($request_secret)) {
// handle unauthenticated access
}
// Your logic here...
}
—
### โ Why This Matters
– Prevents PHP fatal errors in strict environments (like PHP 8+).
– Keeps your plugin compatible with Breakdance and WordPress best practices.
– Avoids admin panel crashes due to missing `$_REQUEST['key']`.
Let me know if you want this wrapped in a function or refactored into a hook for Breakdance compatibility.