PHP 8 TypeError: Magento 2 Category Save Fails with Empty Product Position
Managing product positions within categories is a routine task for any Magento 2 administrator. However, a recently confirmed issue highlights how a seemingly innocuous action—leaving a product's position field empty—can lead to a critical system error, particularly when running Magento 2.4.x on PHP 8. This bug, identified as Issue #41638, underscores the complexities of maintaining a robust e-commerce platform and the subtle impacts of PHP version upgrades.
The Unexpected TypeError: When Saving Categories Fails
The problem manifests during a standard category save operation. If an administrator navigates to Admin > Catalog > Categories, opens a category with at least one assigned product, and then clears the Position input field for that product within the Products in Category section, clicking Save results in a fatal error. Instead of the expected behavior—where an empty position is typically treated as 0—the system throws a TypeError.
Deep Dive into the Technical Glitch
The root cause lies within Magento's backend logic, specifically in how product positions are handled during category updates. The admin JavaScript (catalog/category/assign-products.js, positionChange()) correctly captures the empty input, sending it as an empty string ("") in the posted JSON for the product's position (e.g., {").
The critical failure occurs in the Magento\Catalog\Model\ResourceModel\Category::_saveCategoryProducts() method. While this method correctly casts product positions to integers when inserting new category-product relationships, it behaves differently for updates. In the update branch, it attempts to compute a $delta by subtracting the old product position from the newly posted value:
$delta = $position - $oldProducts[$productId];
Here's where PHP 8's stricter type checking comes into play. Prior to PHP 8, subtracting a non-numeric string like "" might have silently coerced it to 0. However, PHP 8 throws a TypeError: Unsupported operand types: string - string when attempting to perform arithmetic operations on non-numeric strings. This leads to the entire save transaction failing, often accompanied by messages like "Some transactions have not been committed or rolled back," indicating data integrity issues.
The specific error trace points to:
TypeError: Unsupported operand types: string - string
#0 app/code/Magento/Catalog/Model/ResourceModel/Category.php(344): Magento\Catalog\Model/ResourceModel/Category->_saveCategoryProducts(...)
Impact and Resolution Path
This issue, while classified as S3 (affecting non-critical functionality without forcing a workaround, as users can simply input 0 or any number), is significant because it disrupts a fundamental administrative process within the Catalog component. It highlights a common challenge in Magento 2 development: ensuring full compatibility and robust error handling across different PHP versions, especially when upgrading from PHP 7.x to PHP 8.x.
The good news is that the Magento community and core team have confirmed this bug. The issue is marked as "Reproduced on 2.4.x" (including 2.4.7-p10) and has a "Progress: PR Created" label, indicating that an official fix is already in development. The proposed release note confirms the intended resolution: "Saving a category no longer fails when a product position in Products in Category is left empty."
Shopping Mover's Perspective
For merchants considering or undergoing a Magento migration, or those already on Magento 2.4.x with PHP 8, this bug serves as a reminder of the intricate details involved in platform maintenance. Such issues, though seemingly minor, can impact daily operations and user experience. At Shopping Mover, we emphasize proactive monitoring and timely application of patches to ensure a stable and performant e-commerce environment. Understanding these underlying technical challenges is crucial for successful Magento 2 development, upgrades, and seamless operations.