Bug description
When using CACHE_STORE=database and STATAMIC_STATIC_CACHING_STRATEGY=half, requests to URLs with
long query strings (e.g. UTM campaign parameters) hang for 30 seconds and return a 503 response
containing <meta http-equiv="refresh" content="1; URL='...'">, which causes the browser to reload
the page indefinitely. The same URL without query parameters works correctly. Switching to CACHE_STORE=file resolves the
issue immediately.
The static cache middleware (Statamic\StaticCaching\Middleware\Cache) creates a database lock to
serialize page rendering. The lock key is built by appending the full URL (including query string)
to a fixed prefix: {cache_prefix}static-cache-lock-{full_url}. For example:
statamic-cache-static-cache-lock-http://example.com/?utm_source=google&utm_medium=email&utm_campaign=summer_sale_2026_premium_collection&utm_content=banner_top_homepage_hero&utm_term=sofas+modulares+modernos+diseno+italiano&utm_id=campaign_123456789&gclid=EAIaIQob123
This key is 267 characters, exceeding the VARCHAR(255) constraint on the key column of the Laravel's
cache_locks table.
In MySQL/MariaDB with STRICT_TRANS_TABLES enabled, the INSERT fails with error 1406 ("Data too
long"). DatabaseLock::acquire() catches the QueryException and falls back to an UPDATE that
finds no rows (since the INSERT never succeeded), returning false. Lock::block() retries every
250ms for 30 seconds, then throws LockTimeoutException. The middleware responds with 503 + meta
refresh, which the browser immediately reloads — creating an infinite loop.
Projects created with statamic/statamic (statamic new) include a static_cache store in
config/cache.php with a file driver. StaticCacheManager::cacheStore() detects this store via
hasCustomStore() and uses it instead of the default database store, so locks use flock (no
length limit) and the bug never manifests.
Installations where Statamic is added to an existing Laravel project (composer require statamic/cms + php artisan statamic:install) or upgraded from older versions do not get this store added to
config/cache.php, so cacheStore() falls back to the default store (database), triggering the bug.
How to reproduce
Quick steps using Statamic installer:
statamic new statamic-db-cache
cd statamic-db-cache
sed -i'' 's/^CACHE_STORE=file/CACHE_STORE=database/' .env
# configure a MySQL/MariaDB database
sed -i'' 's/^STATAMIC_STATIC_CACHING_STRATEGY=null/STATAMIC_STATIC_CACHING_STRATEGY=half/' .env
sed -i'' "s/'ignore_query_strings' => true,/'ignore_query_strings' => false,/" config/statamic/static_caching.php
# remove 'static_cache' block on config/cache.php
# remove marketing parameters from 'disallowed_query_strings' on 'config/statamic/static_caching.php'
php artisan migrate
php artisan serve
# make a request
curl 'http://localhost:8000/?utm_source=google&utm_medium=email&utm_campaign=summer_sale_2026_premium_collection&utm_content=banner_top_homepage_hero&utm_term=sofas+modulares+modernos+diseno+italiano&utm_id=campaign_123456789&gclid=EAIaIQob123'
Logs
Environment
Environment
Laravel Version: 12.59.0
PHP Version: 8.4.21
Composer Version: 2.9.8
Environment: local
Debug Mode: ENABLED
Maintenance Mode: OFF
Timezone: UTC
Locale: en
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED
Drivers
Broadcasting: log
Cache: database
Database: mysql
Logs: stack / single
Mail: log
Queue: sync
Session: file
Storage
public/storage: NOT LINKED
Statamic
Addons: 0
License Key: Not set
Sites: 1
Stache Watcher: Enabled (auto)
Static Caching: half
Version: 6.19.0 PRO
Installation
Existing Laravel app
Additional details
Proposed fix: hash the URL before using it as the lock key in Cache::createLock(), consistent with how
ApplicationCacher already hashes URLs for response cache keys:
// src/StaticCaching/Middleware/Cache.php
$key .= '-' . md5($this->cacher->getUrl($request)); // always 32 chars
Note that configuring disallowed_query_strings to filter common tracking parameters (UTM, gclid, etc.) reduces the likelihood of hitting this limit but does not eliminate the risk. Any combination of query parameters not covered by that list (like Pinterest epik) and a log SEO-oriented slug that pushes the lock key past 255 characters will trigger the same failure. The only reliable fix is to hash the URL before using it as the lock key.
Bug description
When using
CACHE_STORE=databaseandSTATAMIC_STATIC_CACHING_STRATEGY=half, requests to URLs withlong query strings (e.g. UTM campaign parameters) hang for 30 seconds and return a 503 response
containing
<meta http-equiv="refresh" content="1; URL='...'">, which causes the browser to reloadthe page indefinitely. The same URL without query parameters works correctly. Switching to
CACHE_STORE=fileresolves theissue immediately.
The static cache middleware (
Statamic\StaticCaching\Middleware\Cache) creates a database lock toserialize page rendering. The lock key is built by appending the full URL (including query string)
to a fixed prefix:
{cache_prefix}static-cache-lock-{full_url}. For example:This key is 267 characters, exceeding the
VARCHAR(255)constraint on thekeycolumn of the Laravel'scache_lockstable.In MySQL/MariaDB with
STRICT_TRANS_TABLESenabled, the INSERT fails with error 1406 ("Data toolong").
DatabaseLock::acquire()catches theQueryExceptionand falls back to an UPDATE thatfinds no rows (since the INSERT never succeeded), returning
false.Lock::block()retries every250ms for 30 seconds, then throws
LockTimeoutException. The middleware responds with 503 + metarefresh, which the browser immediately reloads — creating an infinite loop.
Projects created with
statamic/statamic(statamic new) include astatic_cachestore inconfig/cache.phpwith a file driver.StaticCacheManager::cacheStore()detects this store viahasCustomStore()and uses it instead of the default database store, so locks useflock(nolength limit) and the bug never manifests.
Installations where Statamic is added to an existing Laravel project (
composer require statamic/cms+php artisan statamic:install) or upgraded from older versions do not get this store added toconfig/cache.php, socacheStore()falls back to the default store (database), triggering the bug.How to reproduce
Quick steps using Statamic installer:
Logs
Environment
Installation
Existing Laravel app
Additional details
Proposed fix: hash the URL before using it as the lock key in
Cache::createLock(), consistent with howApplicationCacheralready hashes URLs for response cache keys:Note that configuring
disallowed_query_stringsto filter common tracking parameters (UTM, gclid, etc.) reduces the likelihood of hitting this limit but does not eliminate the risk. Any combination of query parameters not covered by that list (like Pinterestepik) and a log SEO-oriented slug that pushes the lock key past 255 characters will trigger the same failure. The only reliable fix is to hash the URL before using it as the lock key.