Magento – After removing category attributes I get errors when reindexing: Undefined offset in Flat.php

attributescategory-attributeeav

After removing category attributes I get these errors in the log file when I reindex "Category Flat Data":

ERR (3): Notice: Undefined offset: 149 in
[…]\app\code\core\Mage\Catalog\Model\Resource\Category\Flat.php on
line 799

ERR (3): Notice: Undefined offset: 150 in
[…]\app\code\core\Mage\Catalog\Model\Resource\Category\Flat.php on
line 799

Options "Use Flat Catalog Category" and "Use Flat Catalog Product" under System->Config->Catalog are disabled.
It seems that category attributes were removed correctly (after that operation all works without any problems), I did it this way in the setup file:

$setup = $this;
$setup->startSetup();
$setup->removeAttribute('catalog_category', 'my_cat_thumbnail1');
$setup->removeAttribute('catalog_category', 'my_cat_thumbnail2');
$setup->endSetup();

And the setup file was configured this way in the module's config.xml:

<config>
    ...
    <global>
        <resources>
            <mymodule_setup>
                <setup>
                    <module>Example_Mymodule</module>
                    <class>Example_Mymodule_Model_Resource_Eav_Mysql4_Setup</class>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </mymodule_setup>
            <mymodule_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </mymodule_write>
            <mymodule_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </mymodule_read>
        </resources>
    </global>
</config>

I investigated the Flat.php file and the line 799 (marked with a comment in the snippet below) is inside this method:

/**
 * Return attribute values for given entities and store
 *
 * @param array $entityIds
 * @param integer $store_id
 * @return array
 */
protected function _getAttributeValues($entityIds, $store_id)
{
    if (!is_array($entityIds)) {
        $entityIds = array($entityIds);
    }
    $values = array();

    foreach ($entityIds as $entityId) {
        $values[$entityId] = array();
    }
    $attributes = $this->_getAttributes();
    $attributesType = array(
        'varchar',
        'int',
        'decimal',
        'text',
        'datetime'
    );
    foreach ($attributesType as $type) {
        foreach ($this->_getAttributeTypeValues($type, $entityIds, $store_id) as $row) {
            $values[$row['entity_id']][$attributes[$row['attribute_id']]['attribute_code']] = $row['value']; //THIS IS THE LINE
        }
    }
    return $values;
}

On line 799, this part of the code: $row['attribute_id'] returns 149. The same number is in the error message:

Undefined offset: 149…

Number 149 is the value of the attribute_id column in the eav_attribute table in database. So 149 is the ID of the attribute that was already removed. The row with this ID in the eav_attribute table doesn't exist anymore (since this attribute was removed). But somehow Magento still tries to get the data of this attribute for some categories.

So this $row['attribute_id'] returns 149. And when Magento tries to get element 149 from this array: $attributes[$row['attribute_id']] it throws error because there is no attribute with ID 149 in $attributes array.

It looks like attributes were removed from the eav_attribute table, but Magento still stores the data of the removed attributes for some categories. If a category had any data in those removed attributes, that data is still stored in the database.

  1. But shouldn't it be removed since I removed the attributes?
  2. Or did I remove the attributes incorrectly?

Best Answer

The eav_attribute's values are still in the entities value tables (catalog_category_entity_text, catalog_category_entity_int, etc.) and therefor the flat indexer is giving you issues.

Easiest way to solve this is to install this N98 Magerun addon https://github.com/magento-hackathon/EAVCleaner and run its eav:clean:attributes-and-values-without-parent command.

Afaik there are no foreign key constraints from the attribute_id column on the value tables to the eav_attribute table, so it doesn't automatically delete them. I'm not sure why..