Issue Summary

10
Total Issues
3
Critical
4
Major
3
Minor
StoreManager::setCurrentStore() Not Thread-Safe
Critical

Description

Calling setCurrentStore() modifies a shared singleton state. In async contexts (message queue consumers, parallel processes), this can cause one process to affect another's store context, leading to incorrect configuration, prices, or content being returned.

Affected Code

  • Magento\Store\Model\StoreManager::setCurrentStore()
  • All code using $storeManager->getStore() after modification

Workaround

// BAD: Modifies shared state $storeManager->setCurrentStore('french'); $result = $this->doSomething(); $storeManager->setCurrentStore('default'); // Might not restore correctly // GOOD: Use store emulation pattern $originalStore = $storeManager->getStore()->getId(); try { $storeManager->setCurrentStore('french'); $result = $this->doSomething(); } finally { $storeManager->setCurrentStore($originalStore); } // BETTER: Use App\Emulation for admin operations $this->emulation->startEnvironmentEmulation($storeId); try { $result = $this->doSomething(); } finally { $this->emulation->stopEnvironmentEmulation(); }

Tags

thread-safety async message-queue state-management
Store Terminology Confusion (Store vs Store Group vs Store View)
Critical

Description

The term "Store" is used inconsistently throughout Magento. In the Admin UI, "Store" refers to a Store Group (middle tier), while "Store View" is the bottom tier. In code, StoreInterface and the store database table represent Store Views. This causes confusion when developers mix up the entities.

Correct Terminology

// Database table mapping: store_website -> WebsiteInterface // Top level (payment, shipping scope) store_group -> GroupInterface // Middle (owns root category) store -> StoreInterface // Bottom (language, theme, URLs) // Admin UI labels: "Website" = Website (correct) "Store" = Store Group (confusing!) "Store View" = Store (correct but verbose)

Workaround

When documenting or discussing: always use "Store View" for the bottom tier, "Store Group" for the middle tier, and "Website" for the top tier. In code reviews, verify that the correct entity is being used.

Tags

documentation terminology architecture
Store Resolution Race Condition on First Request
Critical

Description

Under high concurrency on a cold cache, multiple requests hitting store resolution simultaneously can cause race conditions where stores are resolved incorrectly or the cache is populated with stale data.

Affected Code

  • Magento\Store\Model\StoreResolver::getCurrentStoreId()
  • Magento\Store\Model\StoresData::getStoresData()

Workaround

Warm caches before high-traffic events. Use bin/magento cache:flush followed by a cache warming script that hits each store view URL before going live.

Tags

race-condition caching performance
reinitStores() Performance Impact
Major

Description

Calling reinitStores() clears all store-related caches including scope config, store repositories, and resolver caches. This is expensive and can cause performance degradation if called repeatedly or in loops.

Workaround

// BAD: Calling in a loop foreach ($stores as $store) { $this->updateStore($store); $storeManager->reinitStores(); // EXPENSIVE - each iteration! } // GOOD: Call once after all updates foreach ($stores as $store) { $this->updateStore($store); } $storeManager->reinitStores(); // Once at the end

Tags

performance caching batch-operations
Store Cookie Not Cleared on Store Deletion
Major

Description

When a store view is deleted, existing users may still have the store code in their cookies. While the storeCookieValidate plugin handles this gracefully by clearing invalid cookies, it adds overhead to every request until cookies expire.

Workaround

After deleting a store view, consider flushing Varnish/CDN caches and wait for natural cookie expiration. The system handles invalid cookies automatically but logging may show increased NoSuchEntityException entries during the transition period.

Tags

cookies store-deletion user-experience
Scope Fallback Not Always Intuitive
Major

Description

Configuration fallback follows store -> website -> default. However, this means a value set at the website level will apply to ALL store views under that website, which may not be the intended behavior when adding a new store view.

Example Scenario

// Website "EU" has payment method disabled at website level core_config_data: scope='websites', scope_id=2, path='payment/checkmo/active', value='0' // Adding new store view "German" under EU website // Expected: German store inherits from EU website (checkmo=0) ✓ // But: Developer might expect fresh default values // To override for German store specifically: core_config_data: scope='stores', scope_id=5, path='payment/checkmo/active', value='1'

Tags

configuration scope inheritance
hasSingleStore() Caching Issues
Major

Description

The hasSingleStore() method has a TODO comment noting it should be cached. When called frequently (e.g., in layout XML conditions), it queries the store list multiple times per request.

Affected Code

// From StoreManager.php - note the TODO public function hasSingleStore() { // TODO: MAGETWO-39902 add cache, move value to consts return $this->isSingleStoreAllowed && count($this->getStores(true)) < 3; }

Workaround

Cache the result locally if calling multiple times within the same request context. The store list is cached, so the performance impact is usually acceptable.

Tags

performance caching technical-debt
MAGE_RUN_CODE/MAGE_RUN_TYPE Environment Variables
Minor

Description

Legacy environment variables MAGE_RUN_CODE and MAGE_RUN_TYPE are still supported but not well documented. They can conflict with URL-based store resolution if not configured correctly in web server configuration.

Workaround

// nginx.conf example - set per-domain server { server_name de.example.com; set $MAGE_RUN_CODE "german"; set $MAGE_RUN_TYPE "store"; // ... include magento config } // Or use store code in URL instead (no env vars needed) // web/url/use_store = 1 https://example.com/german/products

Tags

configuration environment nginx
Store Admin (ID: 0) Edge Cases
Minor

Description

The admin store (ID: 0) is a special store that exists for backend operations. Some methods return different results when including or excluding the admin store, which can cause confusion.

Examples

// Without admin store (default) $stores = $storeManager->getStores(); // [1 => Store, 2 => Store] // With admin store $stores = $storeManager->getStores(true); // [0 => Admin, 1 => Store, 2 => Store] // Iterating - be aware of ID 0 foreach ($storeManager->getStores(true) as $store) { if ($store->getId() == 0) { continue; // Skip admin } }

Tags

edge-case admin-store
ScopeInterface Constant Naming (Singular vs Plural)
Minor

Description

ScopeInterface defines both singular (SCOPE_STORE) and plural (SCOPE_STORES) constants. The plural forms are used for database scope values while singular forms are used in method calls. This can cause confusion about which to use.

Usage Guide

// For ScopeConfigInterface methods - use SINGULAR $scopeConfig->getValue( $path, ScopeInterface::SCOPE_STORE, // Correct $storeCode ); // In core_config_data table - uses PLURAL // scope column contains: 'default', 'websites', 'stores' // Both resolve to the same behavior internally

Tags

naming constants convention