Known Issues

Common gotchas, edge cases, and workarounds for shipping development

CRITICAL MAJOR MINOR

Critical Issues

Rate collection silently fails for invalid carriers

CRITICAL

Affected: 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

CRITICAL

Affected: 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

CRITICAL

Affected: 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

MAJOR

Affected: 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

MAJOR

Affected: 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

MAJOR

Affected: 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

MAJOR

Affected: 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

MINOR

Affected: 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

MINOR

Affected: 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

MINOR

Affected: 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