Undefined Index error in PrivacyManager::getPurgeDataSettings()

I’m getting a REALLY strange error on the dashboard page (inside each stats panel).
The error is occuring in the PrivacyManager::getPurgeDataSettings() function.


There is an error. Please report the message (Piwik 2.7.0) and full backtrace in the Piwik forums (please do a Search first as it might have been reported already!).

Notice: Undefined index: delete_logs_enable in ...\piwik\plugins\PrivacyManager\PrivacyManager.php on line 167

Backtrace -->

#0 Piwik\Error::errorHandler(...) called at [...\piwik\plugins\PrivacyManager\PrivacyManager.php:167]
#1 Piwik\Plugins\PrivacyManager\PrivacyManager::getPurgeDataSettings(...) called at [...\piwik\plugins\PrivacyManager\PrivacyManager.php:331]
#2 Piwik\Plugins\PrivacyManager\PrivacyManager::shouldReportBePurged(...) called at [...\piwik\plugins\PrivacyManager\PrivacyManager.php:122]
#3 Piwik\Plugins\PrivacyManager\PrivacyManager::hasReportBeenPurged(...) called at [...\piwik\core\Plugin\Visualization.php:403]
...etc.

The strange part isn’t that theres an undefined index error, the strange part is that i’ve debugged the code and the array key does actually exist, and it still throws this error…

The line of code in question reads:


$settings[$configKey] = $values[$configKey];

If i put a var_dump($values) right above that line, here’s what comes out…


array(5) {
  'delete_logs_enable' => string(1) "0"
  'delete_logs_schedule_lowest_interval' => string(1) "7"
  'delete_logs_older_than' => string(3) "180"
  'delete_logs_max_rows_per_query' => string(6) "100000"
  'enable_auto_database_size_estimate' => string(1) "1"
}

As you can see, the array does indeed contain the key that we’re trying to assign.
Additionally, array_key_exists(‘delete_logs_enable’, $values) returns TRUE!

I can’t for the life of me figure out why PHP is treating this code this way…

PIWIK version: 2.7.0
PHP version 5.6.0

Any ideas would be greatly appreciated.

UPDATE
After running the same tests on all sites, there are widgets that will display without generating this error.
Any widget that has data for the specified period displays without error.
Any widget with no data, first displays the error, then “There is no data for this report.” below the error.

check that the file config/global.ini.php was uploaded correctly from new version ?

Hi Matt,
thanks for the feedback.
I’ve confirmed that the config files were correctly updated.

In an effort to eliminate all possible conflicts, I’ve created a brand new installation in a fresh folder with all but the custom “config.php” pointing to the existing DB… Same problem still occurs.

I have also created another new installation of piwik running on PHP 5.5.15 which DOES NOT suffer this same problem.
At this point I’m starting to think that 5.6.0 may be suffering from some sort of data-type problem, where a string with a given value is not necessarily equal to another string of the same value because they are not the same variable, where as in the case of arrays, one is an array key and the other is a variable.

To illustrate, I’ve done some tests below, where accessing the array value with a string key works, but using a string variable key it throws an exception.

If, when using var_dump() to test this scenario, and dump the array and other variables to see what config values exist, I get the following:

var_dump($values);

array(5) {
‘delete_logs_enable’ => string(1) “0”
‘delete_logs_schedule_lowest_interval’ => string(1) “7”
‘delete_logs_older_than’ => string(3) “180”
‘delete_logs_max_rows_per_query’ => string(6) “100000”
‘enable_auto_database_size_estimate’ => string(1) “1”
}

var_dump($values['delete_logs_enable']);

string(1) ‘0’

var_dump($configKey);

string(18) ‘delete_logs_enable’

var_dump($values[$configKey]);

Throws exception!

I’m going to try and upgrade to PHP 5.6.1 later today to see if the point release has fixed something they didn’t even know was broken.
Will let you know how I go.

In the mean time, changing the code from:


$settings[$configKey] = $values[$configKey];

to


foreach ($values as $key => $value) {
    if ($key == $configKey) {
        $settings[$configKey] = $value;
        break;
    }
}

Has fixed my issue… this seems to now work perfectly, which leads me to believe that the array key accessor may be broken.

it wouldn’t surprise me if the .0 release had major bugs. I couldn’t do better :wink: Though if you keep experiencing the issue in newer versions it would be nice somehow to create a bug report on php.net or check if already exists. Thanks for following up!

Well, some sad news.
This error is still present in PHP 5.6.1.
If I roll-back to PHP 5.5.15 (or earlier) the issue is gone.

Fortunately it’s nice and easy to run several instances side-by-side in my environment, so I’ll stick with 5.5.15 just for my piwik instance for now.

So, how to reproduce this error in a format that can reported to the folks at PHP…???
My suspicion is that the bug lies in array_merge or something that is used to load all of the config values and merge them into a single array object.

I’ll link the issue here once I have a working bug report.

Thanks guys!

So, I’ve done some extended testing of this issue in various environments and managed to reproduce it consistently… In our environments, this error is being caused by enabling OpCache.

We’re using WinCache 1.3.6.1. If we enable OpCache we start seeing this error the second time onward any function is called that accesses the *.ini.php files. The first time the files are loaded everything is successful, from then on it goes to the cached version and everything goes awry.

I’m assuming this is because these files are technically NOT ini files, but PHP files with INI content in them.
This is one way of stopping people from accessing the file by allowing the

; <?php exit; ?> 

at the top.
However, given this issue may occur in more than one platform when OpCaching is enabled, it may be worth making these files actual ini files, and simply preventing ini files from being served via .htaccess/web.config settings.

Using FileCache works fine, but OpCache causes this error to occur.

Our workaround is to Disable OpCache for Piwik only.
In our PHP.INI file, we enable opcache, then specifically disable it for the piwk website.


[WinCache]
...
wincache.ocenabled = 1
[PATH=C:\Hosting\Domains\piwik.mydomain.com\piwik]
wincache.ocenabled = 0

So far, this is the easiest method of dealing with the issue.
I’ll report this to the WinCache folks today now we have a reproducible example.

Cheers everyone.