Critical Issues
Rate collection silently fails for invalid carriers
CRITICALAffected: Model/Shipping.php:310-314
When prepareCarrier() throws a RuntimeException,
the exception is caught and the carrier is silently skipped. This can cause carriers to
disappear from checkout without any visible error.
public function collectCarrierRates($carrierCode, $request)
{
try {
$carrier = $this->prepareCarrier($carrierCode, $request);
} catch (\RuntimeException $exception) {
return $this; // Silent failure!
}
// ...
}
Workaround
Enable carrier debug logging by setting carriers/[code]/debug
to 1 in config. Check var/log/shipping.log for
carrier initialization failures. Add custom logging in a plugin on collectCarrierRates().
Package composition fails silently for overweight items
CRITICALAffected: Model/Shipping.php:420-422
When an item exceeds the carrier's max_package_weight,
composePackagesForCarrier() returns an empty array.
This causes the carrier to return no rates for the entire order with no error message.
if ($checkWeight && $maxWeight && $itemWeight > $maxWeight) {
return []; // Entire order fails, no error shown
}
Workaround
Use a plugin around composePackagesForCarrier()
to detect empty returns and log/display a warning. Alternatively, set realistic
max_package_weight values and validate product
weights during import.
Origin address not validated before rate collection
CRITICALAffected: Model/Shipping.php:207-232
If store origin address is incomplete (missing postcode, region, etc.), rates may be collected with invalid origin data. Carriers may return incorrect rates or fail silently.
Workaround
Always configure complete origin address in Stores > Configuration > Sales > Shipping Settings > Origin. Consider adding a system health check that validates origin address completeness.
Major Issues
Carrier order in checkout is config-dependent, not sortOrder
MAJORAffected: Model/Shipping.php:237-245
Carriers are collected in the order they appear in carriers/*
config, which depends on module load order and config.xml merging. The carrier's
sortOrder config is not consistently used.
Workaround
Sort shipping methods in the frontend using JavaScript after rates are loaded. Or use
a plugin on getResult() to reorder
methods by sortOrder before returning.
Tracking popup exposes order details via hash
MAJORAffected: Controller/Tracking/Popup.php
The tracking popup URL uses a predictable hash parameter. While hashed, the hash algorithm uses order/shipment IDs which could potentially be enumerated.
Workaround
Limit tracking popup access by IP or require customer login. Consider implementing rate limiting on the tracking endpoint.
Label generation locks shipment during API call
MAJORAffected: Model/Shipping/Labels.php
When generating shipping labels, the carrier API is called synchronously. If the carrier API is slow or times out, the admin session may timeout, leaving the shipment in an inconsistent state.
Workaround
Increase PHP and web server timeouts for admin. Consider using async label generation via message queue for high-volume operations. Retry failed labels rather than abandoning shipments.
Free shipping items affect package composition
MAJORAffected: Model/Shipping.php:376-378
Items with free_shipping flag are skipped
during package composition. This can cause package weight calculations to be incorrect
for carriers that ship all items together.
if ($item->getFreeShipping()) {
continue; // Weight not included in package
}
Workaround
Override composePackagesForCarrier() if
you need accurate weight for all items regardless of free shipping status.
Minor Issues
shipping.log grows unbounded
MINORAffected: etc/di.xml (VirtualDebug)
The shipping debug log has no rotation or size limit configured. On high-traffic sites with debug enabled, this file can grow very large.
Workaround
Add logrotate configuration for var/log/shipping.log.
Disable debug mode in production unless actively troubleshooting.
Typo in method name: proccessAdditionalValidation
MINORAffected: Model/Carrier/AbstractCarrierInterface.php:86
The method proccessAdditionalValidation()
has a typo ("proccess" instead of "process"). This is a legacy issue and changing
it would break backwards compatibility.
Note
A newer method processAdditionalValidation()
(correct spelling) exists in AbstractCarrier but the interface still uses the misspelled version.
Cron report aggregation can timeout on large datasets
MINORAffected: Model/Observer.php
The daily shipment report aggregation cron processes all historical data without batching. On stores with millions of shipments, this can timeout.
Workaround
Archive old shipment data periodically. Consider implementing incremental aggregation via custom cron job that only processes new records.
Prevention Best Practices
Configuration
- ✔ Always configure complete origin address before enabling carriers
- ✔ Set realistic max_package_weight limits per carrier
- ✔ Validate product weights during import
- ✔ Disable carrier debug logging in production
Development
- ✔ Always return Error objects instead of null/false for failures
- ✔ Implement proper timeout handling in carrier API calls
- ✔ Add logging at key decision points in custom carriers
- ✔ Test with overweight items and multiple package scenarios
Operations
- ✔ Configure log rotation for var/log/shipping.log
- ✔ Monitor carrier API response times
- ✔ Archive old shipment data periodically
- ✔ Set up alerts for missing shipping rates at checkout
Testing
- ✔ Test rate collection with all carriers disabled
- ✔ Test with international addresses
- ✔ Test with items exceeding max package weight
- ✔ Test carrier API timeout scenarios