CoCart Community 4.9 Release Notes

  • Release date: 4.9.0 shipped 12th July, 2026; this post covers patches through 4.9.3 (20th August, 2026).
  • Backward compatible: No — see Breaking changes below before updating.
  • Database/config update required: No.
  • Minimum requirements: PHP 8.2+ (up from 7.4)
  • Tested with: WordPress v7.1 and WooCommerce v11

PHP 8.2 is now required. PHP 7.4, 8.0, and 8.1 have all reached end-of-life/security support, so CoCart is no longer tested against them as of 4.9.0. Running CoCart on PHP 8.2+ is both a security requirement going forward and a real performance win for the API itself.

ETag support and conditional requests

Cart endpoints and product endpoints (products, categories, tags, attributes, reviews) now support ETags, enabling standard HTTP conditional requests via If-None-Match. A matching ETag returns 304 Not Modified instead of a full payload — meaningful bandwidth and latency savings for clients that poll the cart or product data.

GET /wp-json/cocart/v2/products/123
If-None-Match: "a1b2c3d4e5f6"
→ 304 Not Modified (if unchanged)
→ 200 OK + new ETag (if changed)

Responses on cacheable routes also now include a CoCart-Cache header indicating cache status — HIT, MISS, or SKIP — useful for debugging caching behavior from the client side without needing server access. Add _skip_cache=true as a query parameter on any request to bypass caching for that request specifically. Product routes additionally send a stale-while-revalidate directive for better perceived performance under load.

For third-party routes, developers have three new filters that control which routes participate:

add_filter( 'cocart_etag_cart_routes', function( $routes ) {
    return $routes; // add/remove cart routes from ETag support
});
add_filter( 'cocart_etag_product_routes', function( $routes ) {
    return $routes; // add/remove product routes from ETag support
});
add_filter( 'cocart_etag_routes', function( $routes ) {
    $routes[] = 'your/custom/route';
    return $routes; // opt a third-party plugin's route into ETag support
});

And two others that control age and validation.

add_filter( 'cocart_cache_max_age', function( $seconds ) {
    return $seconds; // default: 1 hour
});
add_filter( 'cocart_stale_while_revalidate', function( $seconds ) {
    return $seconds; // default: 24 hours
});

A settings page, at last

CoCart now has a dedicated settings page (WordPress Admin → CoCart → Settings) for configuration that previously required code:

  • CORS and allowed origin.
  • Authorization-header server variable.
  • Session expiration for guest and logged-in users.
  • Toggles for the “Load Cart from Session” and “Name Your Price” features.

Any setting still controlled by an external filter shows a locked state in the UI with a link explaining what’s controlling it and where. There’s also a new integrations page giving explicit control over which supported plugin CoCart uses when handling a given request, where more than one is active.

Notable fixes

  • The WordPress REST API batch endpoint wasn’t recognized by CoCart and caused a fatal error when adding items through it — fixed.
  • Submitting billing-only details left the shipping address blank; billing fields now mirror to shipping when ship_to_different_address isn’t set, matching native WooCommerce checkout behavior.
  • Shipping packages now also return correctly once a complete address is saved.
  • Slugs, permalinks, and attribute names containing non-ASCII characters (e.g. Chinese, Arabic) are now returned decoded rather than encoded, across all product and cart endpoints — check any client-side code that was working around the old encoded values.
  • Authentication could fail to determine the current user in time when the rest_url_prefix filter was in use, resulting in several cloned guest sessions holding cart items.
  • Fixed a fatal error when adding an invalid product to the cart via the v2 controller (a missing WP_Error check after product validation).
  • The Last-Modified header now correctly uses GMT per the HTTP spec, with more robust date parsing.

Stock validation and password-protected products

4.9.1 (20th July) A maintenance release:

  • Fixed two related stock-validation gaps:
    • the add-item v2 controller wasn’t checking combined stock when an item already existed in the cart, and the “Update Cart” callback wasn’t checking stock before applying a new quantity — both could push a cart’s quantity past available stock.
    • “Not enough stock” error messages were also standardized into one consistent format across v1 and v2.
  • Separately, a scheduled action for plugin update suggestions (cocart_update_plugin_suggestions) was never firing via WP-Cron or WP-CLI because its callback was only registered on admin_init, so Action Scheduler had nothing to call. Issue #576 (reported by community member @isam-aqu).

4.9.2 (12th August) A maintenance release:

  • Fixed password-protected products remaining accessible through the REST API; they now correctly return as an invalid ID when accessed directly and are excluded from listing results.

4.9.3 (20th August) A maintenance release:

  • Changed the password check itself to inspect the product’s password directly rather than relying on WordPress’s post_password_required() function, for more reliable behavior across contexts.

Breaking changes & deprecations

Price overrides on add-to-cart are now disabled by default. The cocart_does_product_allow_price_change filter now defaults to false, meaning the price parameter on POST /wp-json/cocart/v2/cart/add-item no longer overrides a product’s price unless you explicitly opt back in. If your integration relies on passing a custom price when adding items, add this before updating:

add_filter( 'cocart_does_product_allow_price_change', '__return_true' );

or scope it to specific products only:

add_filter( 'cocart_does_product_allow_price_change', function( $allowed, $product ) {
  return in_array( $product->get_id(), array( 123, 456 ), true );
}, 10, 2 );

Don’t forget that the settings page also has a simple toggle to enable the feature.

Deprecated: cocart_secure_registered_users filter → no longer used. Unauthenticated access to a registered user’s cart is now always blocked as a security default; this can no longer be disabled via filter.

The 30-day maximum session-expiration limit (added in 4.6.2) has been removed. Session lifetimes are now fully controlled via the cocart_cart_expiring and cocart_cart_expiration filters, with no hard ceiling. CoCart will still log a warning that very long session lifetimes can affect performance and session-table size.