Skip to content

Known Issues

Critical gotchas, performance traps, and common bugs in Magento_Catalog with proven workarounds. Essential reading before any Catalog development.

4 Critical 5 Major 3 Minor

Severity Levels

Critical: Data loss, financial impact, security risk
Major: Performance issues, incorrect behavior
Minor: Edge cases, non-critical bugs

Critical Issues

getPrice() Returns Base Price, Not Final Price

CRITICAL

Problem

$product->getPrice() returns the base price attribute value only. It does NOT include special prices, tier prices, catalog rules, or customer group pricing.

Impact

Displaying wrong prices to customers. Orders processed at incorrect prices. Financial loss or customer trust issues.

Workaround

// WRONG - Base price only
$price = $product->getPrice();

// CORRECT - Includes all price rules
$price = $product->getFinalPrice();

// BEST - Use pricing framework
$priceInfo = $product->getPriceInfo();
$finalPrice = $priceInfo
    ->getPrice('final_price')
    ->getAmount()
    ->getValue();
Affected: Magento\Catalog\Model\Product::getPrice() | Still Present: 2.4.x

Product Save Race Condition with Stock Indexer

CRITICAL

Problem

When saving products via API without explicit stock data, the stock indexer may run before stock data is properly saved, resulting in products showing as out of stock.

Impact

Products disappear from frontend. Lost sales. Difficult to debug intermittent issue.

Workaround

// Always include stock data explicitly
$stockItem = $product->getExtensionAttributes()
    ->getStockItem();
if (!$stockItem) {
    $stockItem = $stockItemFactory->create();
}
$stockItem->setQty(100);
$stockItem->setIsInStock(true);
$product->getExtensionAttributes()
    ->setStockItem($stockItem);

// Then save
$productRepository->save($product);
Affected: ProductRepositoryInterface::save() | GitHub: magento/magento2#12345

EAV N+1 Query Performance Trap

CRITICAL

Problem

Loading products in a loop using ProductRepository::get() or getById() causes N+1 query issues. Each product load executes 5+ JOINs across EAV tables.

Impact

Page load times of 10+ seconds. Database server overload. Memory exhaustion.

Workaround

// WRONG - N+1 queries
foreach ($skus as $sku) {
    $product = $productRepository->get($sku);
}

// CORRECT - Single query
$collection = $collectionFactory->create();
$collection->addAttributeToSelect(['name', 'price']);
$collection->addFieldToFilter('sku', ['in' => $skus]);
foreach ($collection as $product) {
    // Process
}

// BEST - Use SearchCriteria
$criteria = $searchCriteriaBuilder
    ->addFilter('sku', $skus, 'in')
    ->create();
$result = $productRepository->getList($criteria);
Affected: Any code loading products in loops | Impact: Performance

Category Move Breaks Child Paths

CRITICAL

Problem

Moving categories via API may not properly update all child category paths in certain edge cases, leading to broken navigation and URL rewrites.

Impact

Broken navigation. 404 errors on category pages. SEO impact from broken URLs.

Workaround

// After moving category, force reindex
$indexer = $indexerFactory->create();
$indexer->load('catalog_category_flat');
$indexer->reindexAll();

// Also regenerate URL rewrites
$urlRewriteGenerator->generate($category);

// Verify child paths are correct
SELECT entity_id, path, level
FROM catalog_category_entity
WHERE path LIKE '1/2/moved_id/%';
Affected: CategoryManagement::move() | Still Present: 2.4.x

Major Issues

Flat Catalog Out of Sync

MAJOR

Flat catalog tables may become out of sync with EAV tables if indexers fail silently or are interrupted. Frontend shows stale data.

// Force full reindex of flat tables
bin/magento indexer:reindex catalog_product_flat catalog_category_flat

// Or disable flat catalog if not needed
bin/magento config:set catalog/frontend/flat_catalog_category 0
bin/magento config:set catalog/frontend/flat_catalog_product 0

Product Save Clears Custom Options

MAJOR

Saving a product via repository without including existing custom options will delete them. Options must be explicitly included in save payload.

// Load existing options before save
$existingOptions = $product->getOptions();

// Make your changes...

// Ensure options are preserved
$product->setOptions($existingOptions);
$productRepository->save($product);

Image Gallery Order Not Preserved

MAJOR

When saving product images via API, the position/order of gallery images may not be preserved correctly, resulting in wrong image order on frontend.

// Explicitly set position on each image
foreach ($mediaGalleryEntries as $index => $entry) {
    $entry->setPosition($index);
}
$product->setMediaGalleryEntries($mediaGalleryEntries);
$productRepository->save($product);

Attribute Scope Confusion

MAJOR

Loading products at store scope may return default scope values for website-scoped attributes, leading to incorrect data on multi-store setups.

// Ensure correct store scope when loading
$storeManager->setCurrentStore($storeId);
$product = $productRepository->get($sku, false, $storeId);

// Check attribute scope before trusting value
$attribute = $product->getResource()->getAttribute('my_attribute');
if ($attribute->isScopeWebsite()) {
    // Value comes from website scope, not store
}

Category Assignment via API Triggers Full Reindex

MAJOR

Assigning products to categories via API may trigger full category index rebuilds instead of partial updates, causing performance issues during bulk operations.

// Set indexer to "Update on Schedule" before bulk operations
bin/magento indexer:set-mode schedule catalog_category_product

// Perform bulk category assignments...

// Then manually trigger reindex
bin/magento indexer:reindex catalog_category_product

Minor Issues

Product URL Key Collisions

MINOR

Products with identical names in the same store get auto-generated URL keys that may conflict. Manual URL key assignment is recommended for SEO-critical products.

Special Price Date Timezone Issues

MINOR

Special price from/to dates are stored in UTC but may be interpreted differently in admin vs frontend depending on timezone configuration.

Attribute Option Ordering

MINOR

Dropdown attribute options may not maintain position ordering when exported/imported or when accessed via API. Manual sorting may be required.

Best Practices to Avoid Issues

Development

  • Always use getFinalPrice() for customer-facing prices
  • Use collections instead of loading products in loops
  • Include all extension attributes when saving via API
  • Test with multi-store and multi-website configurations
  • Monitor indexer status during development

Operations

  • Use "Update on Schedule" mode for production
  • Monitor indexer health with cron and alerts
  • Disable flat catalog if not needed for performance
  • Regular database maintenance (ANALYZE, OPTIMIZE)
  • Cache warming after large catalog changes